Live data from Hacker News

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

cl.cam.ac.uk

171–180 of 253 posts

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

#171
post #38

Earlier quoted context omitted.

> C is frequently praised (including in some of the posts here) for its suitability for real-time and embedded systems development, but the author appears to be proposing modifying the C runtime and code generation in ways that, when done in other languages, are claimed to render them unsuitable for these purposes. Don't people think there are things C could improve that wouldn't affect its suitability for these task…

Tagged unions? -- please no... I could be convinced to completely lose unions in C, though (pointer to member or base of struct can be cast to another struct anyway, so losing unions doesn't gain anything; for the same reason tagged unions just would not be useful) Boolean type? Sure, but that would be dependent on use. What is wrong with a bitfield one bit wide instead? What may be useful is "packed bitfield" type (…

Unions would be nice if the syntax for accessing substructure members could be nominally short circuited. For example:

struct ab { int a; int b; };

union c { struct ab ab_short_circuit; int a; };

union c c1; c1.a = 1; c1.b = 2;

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

#172
post #82

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.…

I don't know why it is not common knowledge that different people have different priorities, different ways of thinking about things and, well, that they are different. Not only that but people can even have opinions that contradict their other opinions. I write C, its powerful and that it stays out of the way. I also like assembly for the same reasons. But i also like scheme, that is the most opposite language to C…

Thanks for this post, it's got a lot of wonderful things that we can agree upon.

> I don't know why it is not common knowledge that different people have different priorities, different ways of thinking about things and, well, that they are different.

Obviously there are a lot of things that I will never understand. And people definitely have different priorities. In some cases choosing C (or insert your favorite programming language here) is chosen purely because you've built up a huge amount of experience with it and for the project you're working on you don't want learn something new. That makes a lot of sense. For me the reason Rust is so attractive is for a few reasons, and none of them are about it being zero-overhead, that's just icing on the cake. The Rust design philosophy, type system, threading model, mutability and trait system literally hit every sore spot I've encountered in my career working on distributed systems, especially around concurrency. Things that I started practicing in all of my code, were actually enforced by the compiler, this was so profound that I jumped into it whole hog. To your comment about different ways of thinking about things, it's definitely changed the way I approach problems.

> The whole memory safety argument is.. i want to say "fine" as people do make mistakes, but tools like static analyzers (aka linters) and valgrind exist.

I think back to your comment about priorities, I definitely value correctness over working code (i.e. it can sometimes take longer to get something working in Rust) and performance (I still opt for correctness and working, then go after performing). And clearly valgrind and lints aren't enough for security vulnerable software. But it does really depend on what you're targeting and why.

>> I don't "tell" people, what language to use.

> But you do. If you say to a newbie that their C project is "bad" because it is written in C, be it directly or indirectly, they will take it as if you are telling them to use another language

That's a fair criticism, and I certainly hope I've never said it directly. Here's a recent story I can relate, a friend showed me a really cool embedded system he had built; video, lens, accelerometer, etc. He had gotten it all working, but told me he had wasted an entire day on a use after free bug in his code. I had definitely been strongly encouraging him to look at Rust before this. He showed me what he'd done, it was amazing, I looked at the board type and he could have used Rust, but should he have stopped to learn Rust to do it to save him this one day? Probably not. It took me three hard weeks to learn Rust, but I pushed through and am very happy I did. Should he do this? I guess it becomes a question of how many of those days he thinks he'll run into as he builds in more features... Is it possible he's building the next IoT security disaster? Doubtful as it's a wearable... If he had already known Rust though, I am convinced he could have written the code more quickly and run into fewer bugs, like the one he related.

For the newbies getting started in C, I do think it's a great foundational language to learn. In fact, for no other reason everyone should learn it as it's currently the only reliable lingua franca FFI on most platforms out there. So it's ABI is needed for doing anything between various languages. But at the same time, Rust holds your hand in a way that C does not. It does not let you shoot yourself in the foot in ways that C does, unless you tell it to take the safety off the trigger. So, for newbies getting into systems programming, even though the language can be a little daunting initially, it increases the success rate of producing correct systems code.

> When the truth is that programming languages don't matter in most cases.

Well, clearly in some cases they do, or we wouldn't be having this conversation ;)

> If the program is to be used daily on thousands of computers it starts to be more important that it performs well.

I think we're in agreement through this entire paragraph, and this is where C really excels, but everything you list is also exactly what Rust is really good at. Again, I go back to correctness, this is a huge value of mine in my code. And it's not just the compiler in Rust that helps guarantee correctness, it's also the really excellent #[test] support that is integrated directly into the language. It was the first time I had ever seen that done, where an external testing framework wasn't needed to write tests. It saves so much time in setting up proper tooling and build files, etc. It's freeing.

It sounds like we've had experience with much the same languages, but have come out with some different priorities based on experience. And what person has the right to question another's experiences? Certainly not I.

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

#173

Earlier quoted context omitted.

OpenBSD takes a fairly minimalist approach, which is vaguely described here: http://www.freebsdforums.org/forums/showthread.php?threadid=... They basically replace the unsafe functions with things that are easier to use. Their idea is that it isn't the format of the C-string that causes security issues (null-terminated string), it's the poorly defined functions (with weird corner cases that are hard to get right). It…

I used snprintf(), too, but it is only a minor improvement. Problematic in C is something as simple as concatenating strings: Mystring s,t; t = "hello"; t = cat(s,s); t = cat(s,s,s); t = cat("hello",s); t = cat(s,"world"); t = cat("hello","world"); Even such a simple use case is fraught with major problems: 1. who allocates needed memory? 2. who free's it? 3. can the compiler constant fold cat("hello","world") ? Does…

I assume you're referring to OpenBSD here, they didn't use snprintf(). They used asnprintf(), which solves the problem of who should allocate (but not who should free).

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

#174
post #9

Earlier quoted context omitted.

You are ignoring the fact that many problems can't be solved in the higher level languages. Also, for some, having the c/c++ level of control is prefered.

This doesn't have to be zero sum. We don't need to choose between safe and unsafe. Safety should be a default, with unsafety being something you opt into. C/C++ are both unsafe. Rust is safe by default, and for the cases where you want/need the C/C++ level of access to the system, you can opt into unsafe. I believe Rust is more safe than Go and Java as well, because of the type safety in the threading model. There ar…

[deleted]

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

#175

Earlier quoted context omitted.

I used snprintf(), too, but it is only a minor improvement. Problematic in C is something as simple as concatenating strings: Mystring s,t; t = "hello"; t = cat(s,s); t = cat(s,s,s); t = cat("hello",s); t = cat(s,"world"); t = cat("hello","world"); Even such a simple use case is fraught with major problems: 1. who allocates needed memory? 2. who free's it? 3. can the compiler constant fold cat("hello","world") ? Does…

I assume you're referring to OpenBSD here, they didn't use snprintf(). They used asnprintf(), which solves the problem of who should allocate (but not who should free).

From the link:

"That means that we have been going through the tree cleaning out all calls to sprintf(), strcpy(), and strcat(). Instead, these things are being rewritten to use asprintf(), snprintf(), strlcpy(), and strlcat()."

Maybe the author made a typo.

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

#176
post #14

Earlier quoted context omitted.

I don't like to be told what programming language i should use. You can scoff all you want, but i will be using C for most of my projects.

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.…

I am fluent in c, c++, c#. The performance level difference in implementations in some cases is over five orders of magnitude.

I envy people that don't have to worry or use pointer management. I imagine them coding in rust with one hand while drinking martinies with the other :)

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

#177
post #155

Earlier quoted context omitted.

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…

Not to mention that in C++ there are plenty of string implementations predating std::string (e.g QT's QString, ROOT's TString)

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

#178
post #57

Earlier quoted context omitted.

> I could equally well say that there's no "sane" way to implement a safe owning pointer in C++ unique_ptr + std::move gives you that semantically. Sure it won't stop you from dereferencing a null pointer but, in all the years i've been writing C++, finding and fixing null pointer dereferences wouldn't rank very high on my list of things to worry about. They always kill your program and are easy to spot in an IDE or…

Unique pointers provide no protection against use after free, because you can take a reference to their contents and that reference can become dangling. Because the destructor of a unique pointer is invoked automatically per the language rules, as opposed to in C where an explicit call to free is required, this makes C++ more prone to UAF than C.

It's unusual to take references to the contents of a unique pointer. There is one idiom which says that if one has a smart ptr and a function taking a ref, the raw ptr should be passed, but that's it. It's frowned upon... nay scoffed at to store references one receives as parameters, so that temporary ref will go away after the function call, leaving the smart ptr as unique owner.

This should not be a problem and it certainly doesn't make C++ more prone to use after free. Null pointers are the problem.

Both can be solved though by creating e.g. a safe smart ptr which does null checks and only exposes operator->.

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

#179
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)…

Isn't this a circular argument: C is popular because no other language on the top popularity chart does .

There are many languages with the these properties and better safety, but they aren't popular like C.

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

#180

Earlier quoted context omitted.

I assume you're referring to OpenBSD here, they didn't use snprintf(). They used asnprintf(), which solves the problem of who should allocate (but not who should free).

From the link: "That means that we have been going through the tree cleaning out all calls to sprintf(), strcpy(), and strcat(). Instead, these things are being rewritten to use asprintf(), snprintf(), strlcpy(), and strlcat()." Maybe the author made a typo.

Oh yeah, you're right.

Another thing I've done that will work if you have a lot of strcat(), is make a string struct:

    ktString {
       int len;
       int memlen;
       char *str;
    }
It keeps track of the string's actual length, and the size of the underlying buffer. Then you can 'override' the various string functions:

    bool ktStrcat(ktString s1, ktString s2);
    bool ktSprintf(ktString s1, ...);
These functions will take care of buffer-size checking, and reallocation if necessary. For cases where you need to interface with pre-existing libraries, you can return a cstring(). Make it a function/macro to enable you to change the struct definition in the future:

     #define ktCstr(x) (x)->str

then you can pass it into write() or whatever you need:

    write(sock, ktCstr(s), s->len);
Post reply on HN