Live data from Hacker News

How can C Programs be so Reliable? (2008)

tratt.net

91–100 of 230 posts

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

#91
post #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 la…

> Most sane languages [3] give you exception hierarchy

Go being a glaring exception -- and this is a good thing.

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

#92
post #79
post #67

Earlier quoted context omitted.

Embedded systems like this do not use dynamic memory allocation.

Related: The JPL C guidelines forbid dynamic memory allocation: http://lars-lab.jpl.nasa.gov/JPL_Coding_Standard_C.pdf (HN discussion: https://news.ycombinator.com/item?id=4339999 ) They also demand that code be littered with sanity checking assertions.

Thanks for posting this.

Tangent, I was thinking about Toyota's software process failure and how they _invented_ industrial level mistake proofing yet did not apply it their engine throttle code.

C is obviously the wrong language, but from a software perspective they should have at least tested the engine controller from an adversarial standpoint (salt water on the board, stuck sensors). That is the crappy thing about Harvard architecture cpu (separate instruction and data memory), you can have while loops that NEVER crash controlling a machine that continues to wreck havoc, sometimes you want a hard reset and a fast recovery.

http://en.wikipedia.org/wiki/Crash-only_software

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

#93
post #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 la…

Yes!

Most software I've seen can be dramatically improved by removing exception handlers. (And then fixing the underlying problems).

On the server side I prefer one exception handler which is the OS, it will kill your process, release and free all memory, file handlers, etc. Then I wrap it in a bash script / other monitoring tool, and have it immediately restart whenever it fails.

As for the server itself I'll also add an automatic reboot to the server to ensure nothing out of the ordinary persists for very long (like that PATH modification that someone forgot to add in the appropriate place to get set on restart). If it's virtualized I prefer to destroy the entire server if possible.

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

#94
post #26

Earlier quoted context omitted.

"Discipline" is indeed the right word. I was taught C at Epitech. A single segfault, no matter insidious, was a valid reason to render a whole project NULL. We often had evaluations ran with LD_LIBRATY_PATH=malloc_that_fails.so or just piping /dev/urandom to stdin... Needless to say, calling exit() when a call to malloc() failed wasn't an acceptable recover routine.

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

I grew up using the Amiga, when having memory allocation fail was routine (a standard Amiga 500 for example, came with 512KB RAM, and was rarely expanded to more than 1MB, so you would run out of memory).

What you do when malloc() fails depends entirely on your application: If a desktop application on the Amiga would shutdown just because a memory allocation failed, nobody would use it. The expection was you'd gracefully clean up, and fail whatever operation needed the memory, and if possible inform the user to let him/her free up memory before trying again.

This expectations in "modern" OS's that malloc never fails unless the world is falling really annoys me - it for example leads to systems where we use too much swap to the point where systems often slow down or become hopelessly unresponsive in cases where the proper response would have been to inform the user - the user experience is horrendous: Swap is/was a kludge to handle high memory prices; having the option is great, but most of the time when I have systems that dip into swap, it indicates a problem I'd want to be informed about.

But on modern systems, most software handles it so badly that turning swap off is often not even a viable choice.

Of course there are plenty of situations where the above isn't the proper response, e.g. where you can't ask the user. But even for many servers, the proper response would not be fall over and die if you can reasonably dial back your resource usage and fail in more graceful ways.

E.g. an app server does a better job if it at least provides the option to dynamically scale back the number of connections it handles rather than failing to provide service at all - degrading service or slowing down is often vastly better than having a service fail entirely.

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

#95
post #49

There are multiple factors that contribute, but here's a few that I haven't (to the best of my recollection) seen mentioned so far: tooling (crucial), "do the simplest thing that could possibly work" attitude brought about by (lack of) a built-in collections library and simple syntax, and lack of rapidly changing requirements during development. Tools for C are powerful, mature, and available on near every platform.…

The other day I was quite surprised to learn that the first version of memcached was written in Perl - thinking something like that should be obviously written in C, or else could never make LAMP systems faster... :)

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

#96
post #43

Earlier quoted context omitted.

What's the point of propagating all errors way up to main if you're only going to exit anyway? I think we know how to indicate errors in C functions. What to do about specific errors, in this case allocation failures, is a more interesting question.

If malloc() fails now, it might succeed again later. So you can just go on doing everything else you were doing, then try the memory-hungry operation again in the future. For example, this could be important in systems where you might be controlling physical hardware at the same time as reading commands from a network. It's probably a good idea to maintain control of the hardware even if you don't have enough memory…

This is a pet peeve of mine with modern applications: So many of them just throw their metaphorical hands in the air and give up.

Prior to swap and excessive abuse of virtual memory this was not an option: If you gave up on running out of memory, your users gave up on your application. On the Amiga, for example, being told an operation failed due to lack of memory and given the chance to correct it by closing down something else was always the expected behaviour.

But try having allocations fail today, and watch the mayhem as any number of applications just fall over. So we rely on swap, which leaves systems prone to death spirals when the swap slows things down instead.

If embedded systems programmers wrote code the same way modern desktop applications developers did, we'd all be dead.

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

#97
post #95
post #49

There are multiple factors that contribute, but here's a few that I haven't (to the best of my recollection) seen mentioned so far: tooling (crucial), "do the simplest thing that could possibly work" attitude brought about by (lack of) a built-in collections library and simple syntax, and lack of rapidly changing requirements during development. Tools for C are powerful, mature, and available on near every platform.…

The other day I was quite surprised to learn that the first version of memcached was written in Perl - thinking something like that should be obviously written in C, or else could never make LAMP systems faster... :)

Keep in mind the date it was written -- this was before SSDs and in the days of tiny heaps. Any improvement upon seek times of what were then commodity disks (SCSI/SAS being insanely expensive and out of bradfitz' reach, afaik) would easily dominate the cost of Perl's runtime (which, in retrospect, isn't horribly bad -- the GC and VM are more mature and less trouble-prone than most common scripting languages, although nowhere near LuaJit or any modern Scheme/Common Lisp implementation).

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

#98

Tarsnap is the classic example of a C program whose reliability almost defies belief. Its codebase is large; it solves a very hard problem; and it manages to handle almost every cornercase flawlessly. (As of the latest version, it seems to handle every cornercase flawlessly, as far as I know.) But I've always wondered: if Colin were as experienced with Python as he is with C, would Tarsnap be better served by writing…

> the reason why HN is good

I don't get this.

I would chose reddit over HN any given day technically / ergonomically speaking.

Actually if https://news.ycombinator.com was returning a 301 to https://reddit.com/r/hackernews I would be very happy.

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

#100
post #86

Earlier quoted context omitted.

The most common way to indicate that an error has occurred in a C function is to return non-zero. If this is done consistently, and return values are always checked, an error condition will eventually make its way up to main, where you can fail gracefully. For example: int a(void) { ... if (oops) { return 1; } return 0; } int b(void) { if (a(...) != 0) { return 1; } return 0; } int main(void) { if (b(...) != 0) { exi…

This is a brilliant example of why you'd want exceptions. Look at what you're doing for error handling, manually every time. Exceptions do the exact same thing, except: 1) automatically 2) type-safe 3) allow you to give extra detail about the error 4) tools can actually follow the control flow and tell you what's happening and why 5) debuggers can break on all exceptions. Try breaking on "any error" in your code (I d…

    This is a brilliant example of why you'd want exceptions. Look at what you're doing for error handling, manually every time.
You say that like safely handling exceptions is trivial. Exceptions are emphatically not "better in every way", they are a mixed bag. They offer many clear benefits (some that you have described here), but at the cost of making your code more difficult to reason about. You essentially end up with a lot of invisible goto's. Problems with exceptions tend to be much more subtle and hard to debug.

I'm not against them at all, and often I prefer them, but there are certainly downsides.

Post reply on HN