Live data from Hacker News

How can C Programs be so Reliable? (2008)

tratt.net

61–70 of 230 posts

Re: How can C Programs be so Reliable? (2008)

#61
post #19

The author makes a good point about the discipline imposed by not having exceptions. Programmers tend to write code in one of two modes: the quick-and-dirty mode where you consistently don't check return values, or the built-to-last mode where you consistently do. If you start in the first mode and have to fix a bug, you often have to add error checking all up and down the call chain from where it occurs to where it'…

It depends on the problem you're trying to solve, I think. Let's consider a command line application that fetches a URL, like wget. Without exceptions, you would check the return code of all the system functions you call (dns, sockets, etc), and if any of them fail you can't really recover. You just write out an error message and exit. With exceptions, you could wrap the whole thing and if any system function throws…

> Now put the url fetch code into a larger application. With exceptions this is pretty easy - you can catch any exception thrown by your url fetch code and then retry it a few times until it succeeds, or you inform the user of the app. Without exceptions this is tougher as you need to unroll everything manually in order to retry.

Unless you have something like goroutines - or Erlang-style processes - and perhaps employ a moderately disciplined coding style. Retrying those is just a matter of relaunching them, isn't it?

Also, Common Lisp got exceptions mostly right. Many other languages...not so much, I guess.

Re: How can C Programs be so Reliable? (2008)

#62

The author's point is weakened by the fact that the Converge VM is now (5 years after this article) written in python: https://github.com/ltratt/converge/search?l=c (as of https://github.com/ltratt/converge/tree/08dadda29b/vm ). Compare https://github.com/ltratt/converge/tree/converge-1.x/vm . "there are some obvious reasons as to why it might be so reliable: it's used by (relatively) large numbers of people, who hel…

> The author's point is weakened by the fact that the Converge VM is now (5 years after this article) written in python

Kinda, it's written in RPython, a restricted and statically inferable subset of python built specifically to write VMs.

Re: How can C Programs be so Reliable? (2008)

#63
Popular C software is so reliable because of enormous amount of effort spent developing, testing, and polishing it over many years - not because error handling in C is superior to that in higher-level languages.

If your python script sticks around for 30 years constantly being used by millions of people - I bet it will be rock solid as well. All other things [1] being equal [2], a program written in a higher-level language will likely be more reliable - simply because it will likely be shorter. C has many properties conductive to great longevity of software written in it, but error handling is not one of them.

Now, to the rant about not knowing the exact number of exceptions a function can throw. Most sane languages [3] give you exception hierarchy. You know that every function can throw an Exception (or Throwable, or whatever the root of all things evil is called in your language), and you either handle it or let in propagate. The important bit is you catch exceptions based on what you can handle in a current context, not on what the functions you call can throw [4]. As long as you realize that every call can potentially throw, it is not important what exactly is thrown - letting you abstract away the exact nature of an error is a feature, not a bug, that's what exceptions are there for! Let's say some function deep below changed and now throws a new exception type. So what? It didn't change what you can handle, so there's no reason to modify calling function - just let the exception propagate. What if nothing in your program can handle that exception? You let it crash (hopefully to the debugger, and no, it's not ironic that I suggest it in a topic about reliable programs - crashing is a reliability feature invented to expose problems that would be hidden and hard to debug otherwise). Of course you may also put a few catch-all clauses in a very limited number of strategic places.

If you approach exceptions this way they are vastly superior to error codes.

[1] Scope of the problem, amount of effort spent on development, programmer skills

[2] Or at least on the same order of magnitude

[3] With a notable exception of C++ - I'm not sure what they were smoking when they decided that throwing arbitrary values is a good idea

[4] And this, by the way, is what's wrong with checked exceptions in Java

PS. Didn't mean that having no exceptions is insane - but that if a language has exceptions, the sane thing to do is to organize them in a hierarchy with a single root.

Re: How can C Programs be so Reliable? (2008)

#64
post #26

Earlier quoted context omitted.

> Needless to say, calling exit() when a call to malloc() failed wasn't an acceptable recover routine. What do you do when malloc fails? A bit of graceful shutdown and logging seems like it would be in order, but otherwise how do you keep rolling if mallocs start failing? It seems to me like that would indicate something has gone unusually wrong and full recovery is futile.

Go ahead. Call exit(). On your HTTP/IRC/anything server. Just because you couldn't allocate memory for one more client. Now your service is down and the CTO is looking for blood =) Yes, it's far-fetched and like some said further down the comments, you "can't" run out of memory in Linux, but straight killing a service is never good.

If your server's running Limux, it's going to kill your process with no questions asked if you run out of memory. You're better off practicing crash-only error recovery and having robust clients that can handle a reconnect.

HTTP is stateless already, so crash and restart all you want!

Re: How can C Programs be so Reliable? (2008)

#65
post #17

The author makes a good point about the discipline imposed by not having exceptions. Programmers tend to write code in one of two modes: the quick-and-dirty mode where you consistently don't check return values, or the built-to-last mode where you consistently do. If you start in the first mode and have to fix a bug, you often have to add error checking all up and down the call chain from where it occurs to where it'…

Well I think this is only a problem with runtime exceptions. You have no choice but to deal with compile time exceptions (of course you can deal with them poorly if you choose). But it seems the compile time exceptions are unpopular. I think there's another way to deal with this and that's a better type system. AFAIK it's impossible to have a null pointer exception in Haskell. EG: If you do something like `hashmap.ge…

Haskell's type system isn't powerful enough to guarantee no exceptions will occur, though it certainly manages NULL better and other languages like Agda go further.

Try debugging an out of bounds array access in Data.Array, which IIRC a few years ago just made my program print "error" and die...

Re: How can C Programs be so Reliable? (2008)

#66
It is an interesting observation. I have found that scripted languages are unreliable as a function of loadable modules (which is to say they depend on some module that gets loaded, that at some point changed, and then broke the script). C has that problem too with shared libraries but there are generally fail stop policies in place (if you can't get the version you were linked against exit rather than try to valiantly proceed)

What is perhaps most important is that software does not "rot" in the sense of building materials becoming weaker after exposure to the elements. But it does fair poorly against changes in things it assumes to be true. Some languages, like Ada or Mesa, which have very detailed configuration specifications, achieve high reliability at the cost of high configuration specificity. That makes them brittle against even modest changes in their environment.

The art is striking the balance. Take something like thttpd, 20 year old code still compiles, still does exactly what it always did (simple HTTP web server) very reliable. But the barest minimum of reliance on the ambient environment it runs in.

Re: How can C Programs be so Reliable? (2008)

#67

Earlier quoted context omitted.

I don't get the sense that there was any attempt to recover from errors - it sounds more like they were enforcing that error checking occurred, by replacing `malloc` with one that just returned `NULL` always. It sounds like the goal was to make sure that one didn't assume `malloc` would always succeed and just use the memory. Indeed, recovery is basically futile in this case and your program is going to shut down pre…

What if you application is the fly-by-wire for an airliner? Can you imagine that there might be better options than just calling abort(3)?

Embedded systems like this do not use dynamic memory allocation.

Re: How can C Programs be so Reliable? (2008)

#68
post #21

The author makes a good point about the discipline imposed by not having exceptions. Programmers tend to write code in one of two modes: the quick-and-dirty mode where you consistently don't check return values, or the built-to-last mode where you consistently do. If you start in the first mode and have to fix a bug, you often have to add error checking all up and down the call chain from where it occurs to where it'…

Your experience with languages with exceptions seem to come from people who misuse them. Randomly placing catch clauses around in the code is not good practice, even if perhaps a majority of all programmers in safe languages code that way. That causes latent bugs that are incredibly hard to debug. The trick is to almost never ever catch exceptions. For example, in his post he describes a bug caused by accessing beyon…

"Your experience with languages with exceptions seem to come from people who misuse them."

Yes, it does, because people who misuse them seem to be a majority. I think that's an important point in language (or for that matter any kind of) design. You can't just look at how well things work for the experts - a mistake made by both Common Lisp and C++ in different ways). Nor can you just consign all non-experts to some straw-man-ish "blub" category. You have to look at what skill level is required to make the benefits outweigh the costs, which could be anywhere along the skill continuum, and compare that to the actual skill distribution of the programmers you have (or will have after hiring and/or training).

The sad fact seems to be that the tipping point for exceptions is at a point that leaves most programmers on the bad side. The same is almost certainly true for any kind of meta-programming. It might even be true for closures and continuations. "Primitive" languages lacking features like exceptions or GC surely do trip up the true beginners, but leave fewer traps further along the path.

Re: How can C Programs be so Reliable? (2008)

#69
post #37

"Once one has understood a concept such as pointers (arguably the trickiest concept in low-level languages, having no simple real-world analogy) " huh? So when you write a letter to someone, you actually attach their house onto the outside of the envelope? No of course you don't. You write their ADDRESS on the envelope. All this lore about how difficult pointers are, is bunk. The syntax of pointers vs addresses vs de…

Agreed, in theory - in practice, I find that explaining

mov r1, r2 vs mov (r1), r2 vs mov (r1)+, r2

followed by an hour of writing assembler programs to do basic things with null-terminated strings is usually needed to help people learning C to quickly internalize what that means.

Something about * and + and - around the var name seems to become easier when they can say "oh now I see; *c++ is like (r1)+".

Re: How can C Programs be so Reliable? (2008)

#70
I should note that less experienced programmers tend to start with higher level languages, as a rule, so the average experience of a C programmer is likely higher than that of the HLL programmer. This general experience level alone gives the resulting code a reliability boost.
Post reply on HN