Live data from Hacker News

Some Were Meant for C: The Endurance of an Unmanageable Language [pdf]

cl.cam.ac.uk

151–160 of 253 posts

Re: Some Were Meant for C: The Endurance of an Unmanageable Language [pdf]

#151

You can pry gcc out of my cold, dead hands when your fancy type-safe high level languages will let me do things like: * Fork a running program to enable analysis or serialisation of program state without blocking, or * Use mmap to allocate all my datastructures on disk, or * Have full control over what happens when my program receives a signal, or * exec another program but have it to inherit all the open file descri…

Half of the things you mention are related to system calls, any language that has a C ffi/provides syscall in stdlib will let you that.

Re: Some Were Meant for C: The Endurance of an Unmanageable Language [pdf]

#152

Earlier quoted context omitted.

> This went ok, but I still have no idea which of the 6 string types I should use for a library like that. None of Swift, Go or C have this problem. There are two string types: a string that owns its contents and a string that references its contents. This is the same as in any language that uses smart pointers for resource management. Can you name a string type that you think should be removed, and explain why? > Fi…

> There are two string types: a string that owns its contents and a string that references its contents. This is the same as in any language that uses smart pointers for resource management. There's String, &str, Cow , Rc and other variants. None is canonical. I spent about 2 hours reading documentation trying to pick the right type to use and I think I ended up with Rc >. But in this instance my strings represent ch…

Have you considered C#? It only has a single string class. With async-await, concurrency is fine too.

Not long ago, they open sourced the compiler and a subset of runtime, making it cross-platform: https://github.com/dotnet/core It’s a but tricky to install on Linux, but for me it works OK, at least so far (an embedded TCP/UDP server app).

Re: Some Were Meant for C: The Endurance of an Unmanageable Language [pdf]

#153
post #126

Earlier quoted context omitted.

In my case, nearly 100% of the C code I write is for embedded systems. Casting a hex literal to a pointer type that is a volatile hardware register is better than dropping into asm.... So yes, compilers will always have a hard time understanding device drivers and such unless you turn hardware device concepts into language primitives.

A more correct thing would probably be to create linker scripts that expose symbols for the registers. It's probably not worth the trouble now but the hypothetical compiler would understand it better.

There still needs to be a description of the underlying hardware behavior somehow. The hardware engineers often give you a somewhat correct Excel sheet or force you to look at the HDL to figure it out.

Re: Some Were Meant for C: The Endurance of an Unmanageable Language [pdf]

#154

Earlier quoted context omitted.

I don't "tell" people, what language to use. But I do encourage them to look at new languages, especially ones that fit in the same place as one that they like. I love C. It was my first programming language. I love the syntax, I love the semantics. Years ago, I left it though, because I could deliver higher quality applications with fewer unknown bugs with Java, but I always wanted to find a reason to go back to C.…

When I checked out Rust a year ago, I immediately discovered it has no SIMD (SSE, AVX, Neon). That it has no sane ways to implement a graph structure. Also that it’s hard to compose data structures into higher-level specialized ones. Also, I highly encourage people who worry about pointer management all the time to checkout modern C++.

I haven't learned rust because of how annoying the rust evangelism is everywhere I read about it.

Re: Some Were Meant for C: The Endurance of an Unmanageable Language [pdf]

#155

Earlier quoted context omitted.

That particular problem (strlen/strcpy/memcpy) comes from the problems of the standard library string functions. It can be solved by creating your own string library. Then string manipulation is easy.

That falls over as soon as you integrate with anybody else's C code, including the operating system APIs, and with C string literals :-( If it was as easy as you say, it would have happened. And heaven knows I wrote my own string packages, one after the other, and so did everyone else. I eventually abandoned all of them. C's abstraction abilities are simply not good enough to do a decent string encapsulation.

No other language solves this perfectly either, certainly not in a way that interoperates _across_ languages and environments.[1] Which is pretty much the whole point of the article. But what C excels at is the ability to write code which can examine and work with the representation of most string-like objects exported from any environment. The difficulty of doing so is a function of how opaque and complex the alien implementation.

I gave up on trying to solve strings in C applications a long time ago, too, much as you have. I did so not because I found C too inexpressive, but because I realized that I was trying to shoe-horn too many concepts into a "string". A string is almost by definition the wrong data structure--either too abstract or not abstract enough--for almost everything. Not coincidentally, that was about the same time I stopped abusing regular expressions for parsing data.

[1] Even C++ didn't solve this. We're still in the midst of a std::string ABI compatibility break in the C++ ecosystem. Granted, it's been about 12 years since the last one, but these last fairly long because systems software (i.e. infrastructure software) has a really long tail.

Re: Some Were Meant for C: The Endurance of an Unmanageable Language [pdf]

#156
post #113
post #5

This is a long paper and the author has 2 main claims: 1) C Language popularity is more to do with cognitive ease of memory addresses as a conceptual model for inspection and change. Author claims memory address mental model overshadows runtime performance . 2) switching to "safe" languages like Java/C#/Rust is not necessary. With no changes/violations to existing C Language specification, a new/different implementat…

C's popularity is due to the fact that it is predictable within certain bounds (single thread or limited concurrency). No GC pauses, no weird runtime crashes due to a strange constructor, no gigantic exception chains, etc. The only languages in the TIOBE index that can even try to make that claim are: C at #2, C++(if you subset it) at #3, Objective-C/Swift(#18/#11), Assembly at #14, Ada at #29, and maybe FORTRAN(#35)…

C's popularity is due to the fact that it is predictable within certain bounds (single thread or limited concurrency).

Your post, and reading a discussion further down about Rust's reference counting, has made me realize something primitive that Rust is getting right--a real move forward--which even those who don't enjoy the default "safety switch" being flipped from C (like me) may agree.

The C model for memory in time and space is so clean for heap data and the function call stack for one thread (plus global registers), but C has no community-understood/concurring model when it comes to concurrency.

Rust, older C++ libraries, C malloc implementations, and other are all alluding toward the simple memory model for multiple threads, which is reference counted pointers, IMO. Basically use a separate type of pointer for heap data, where the max size of the heap is divided by whatever binary power of 2^p processors exist.

Rust folks or other languages are welcome to add more ownership semantics or whatever, but the whole family of languages could benefit by this extension to the lingua Franca of C. We may not even need to add a new nominal pointer type to C, just by fiat understand and expect shared, free store objects to always live inside the lowest 1/p th portion of the word address space.

Re: Some Were Meant for C: The Endurance of an Unmanageable Language [pdf]

#157

Earlier quoted context omitted.

I'm really not sure, but I think there's a miscommunication about raw pointers in this thread. I think other folks are suggesting that you can solve the container composition problems you're talking about by inserting raw pointers into a HashMap. But I think you're reading that as obtaining raw pointers to the storage that a HashMap owns, which is why you're worried about iterator invalidation rules and stuff like th…

To create an external index for the existing collection, I need to get pointer of the item stored in that existing collection, compute a key, and put both into the HashMap So, I need to do both. And also, I need to know when these pointer expire so I can rebuild my index when it happens.

I think I understand. The idea would be to have one HashMap that holds the objects themselves, and then a secondary HashMap (with a star this time) that indexes on some other key and points to values stored directly in the first map?

What's the benefit of doing that, compared to making both the HashMaps store pointers to independently allocated objects on the heap, such that insertions into one map never invalidate the other map? Is the hope to avoid paying the cost of an extra pointer dereference when we're using the first map? Or does independently allocating each object hurt cache locality or something like that?

Re: Some Were Meant for C: The Endurance of an Unmanageable Language [pdf]

#158

Earlier quoted context omitted.

> There are two string types: a string that owns its contents and a string that references its contents. This is the same as in any language that uses smart pointers for resource management. There's String, &str, Cow , Rc and other variants. None is canonical. I spent about 2 hours reading documentation trying to pick the right type to use and I think I ended up with Rc >. But in this instance my strings represent ch…

Have you considered C#? It only has a single string class. With async-await, concurrency is fine too. Not long ago, they open sourced the compiler and a subset of runtime, making it cross-platform: https://github.com/dotnet/core It’s a but tricky to install on Linux, but for me it works OK, at least so far (an embedded TCP/UDP server app).

I haven't, and its a good idea. I wrote a bunch of C# code back in 2007 and I consistently enjoyed it. - It seems like a very pragmatic language choice.

But if I'm going to move further away from the hardware in exchange for some language comforts & quality of life improvements, Elixir is the next language I want to try. I think both its concurrency primitives and immutability rules might be the right language-level defaults.

Re: Some Were Meant for C: The Endurance of an Unmanageable Language [pdf]

#159

Earlier quoted context omitted.

> And when I want to compose 2 data structures into my own higher-level one, for performance and memory access patterns I need these two lower-level structures to expose unsafe stuff at their API boundaries. The data structures I saw don’t do that, they’re designed to be consumed from safe Rust instead. Can you give a specific example of something you want to do that you can't? > I think in modern C++, with these ite…

> Can you give a specific example of something you want to do that you can't? Compose a hash map + linked list into an LRU cache. Rust how has that in standard library, but they had to implement their own linked list for that. In C++ it’s just a few lines of code, because standard maps+lists compose just fine. Or (more generic example and thus harder to put in the standard library), add an index to existing collectio…

> In my experience, use after free = instant crash in debug build. Quite easy to detect and fix.

The security track records of major network-facing C++ apps disagree with you.

Re: Some Were Meant for C: The Endurance of an Unmanageable Language [pdf]

#160

Earlier quoted context omitted.

Use an Rc? If you can't afford the reference count, then use unsafe/raw pointers, which it sounds like you'd do in C++ anyway.

> then use unsafe/raw pointers Even if I manage to extract an unsafe pointer from that Rust collection, I don’t know for how long will it work. For C++ collections, iterator invalidation rules tell me that.

> For C++ collections, iterator invalidation rules tell me that.

The iterator invalidation rules in Rust are straightforward, more straightforward than those in C++. They have to be, because the compiler actually checks them.

Post reply on HN