Live data from Hacker News

How can C Programs be so Reliable? (2008)

tratt.net

171–180 of 230 posts

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

#171
post #8

Earlier quoted context omitted.

Wait, HN is good? The community is interesting, but I've never been particularly impressed by the implementation. In particular, the "feature" where "More" links and such randomly expire after a while just screams "shoddy implementation" to me.

The thing is, the "more" links are specific to each user and generated page. They're not just "page 3 at the time you click on the link", but the actual next 30 links following the 30 it's previously shown you. As a result, it needs to store state for each of these links it's created (IIRC, the fnid is a reference to the closure containing that state). For obvious memory management purposes, these need to be expired…

And why not store that state on the client? 30 serialized ids is not that much.

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

#172
post #96

Earlier quoted context omitted.

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

> If embedded systems programmers wrote code the same way modern desktop applications developers did, we'd all be dead. If Boeing made passenger jets the way Boeing made fighters, we'd all be dead, too, but try telling a fighter pilot that they should do their job from a 777. It's two very different contexts. Besides, some errors can't be recovered from. What do you do when your error logging code reports a failure?…

>What do you do when your error logging code reports a failure? Keep trying to log the same error, or do you begin trying to log the error that you can't log errors anymore?

First you try to fix the problem of the logging system by runnig a reorganisation routine (delete old data,...) or reinit the subsystem. If that does not work AND if logging is a manadatory function of you system you make sure to change into a safe state and inidcate a fatal error state (blinking light, beeper, whatever). If the logging is such an important part of the system surrounding your system it might take further actions on its own and reinit your system (maybe turn your system off and start another logging systen). There is no exit. You never give up.

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

#173
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…

Also, exceptions are faster.

There is a lot of comparisons and branching going on, when the program always checks return codes. Assuming zero-cost exceptions, there is only overhead in the failure case.

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

#174
post #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.

Is /r/hackernews officially restricted by Reddit or what is going on there?

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

#175

C programmers have better culture. Than say Java programmers. If I was a swordsman and had a rusty sword and you had a new one, the sword does not decide the fight.

Yes, mainly because new sword has an auto-grinder welded to it that might start running at any given moment, even if you are in a deathly fight :-)

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

#176
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…

If this were valid, there would be no need for an exception type hierarchy at all.

In reality, we have different exception types (and error codes) because there are circumstances when the type of exception determines how it may be handled. Therefore, a professional programmer needs to be able to find out what exceptions could occur in any given call (which is not the same as saying that she needs to consider each one individually after every call - this is where your 'what can be handled here?' principle has some use.)

Terminate-on-exception might just be a workable policy for a simple or unimportant application, but it is not how you create a robust software infrastructure or safety-critical software.

The original article describes a style of programming in which his programs are built directly on OS services without middleware, and in which the programmer is aware at all times of what might go wrong. I think it is this, rather than the distinction between error codes and exceptions, that contributes to the reliability of the programs he is writing about.

Creating a new exception type that could propagate out of the abstraction you are working on is a serious matter, so it would not be a bad thing if it were a non-trivial thing to do. Unfortunately, the attempts to make this so in Java and C++ put most of the burden on the users of the abstraction instead, and this seems to be built in to the nature of this problem.

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

#177
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…

Or, writing C software with an acceptable quality requires you to put relatively big effort in developing, testing and polishing; the result of which is usually higher quality than what you get in a language where things are easier to write and you don't feel you have to be careful.

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

#178

Earlier quoted context omitted.

> The trick is to almost never ever catch exceptions. I strongly disagree. Not catching exceptions leaks abstraction layers. If I have a Prefs::save() method, I don't want it throwing a DiskFullException when the Prefs class is an abstraction of a preferences datastore. I don't care what is the final store, as long as it fits the abstraction. A well designed abstraction will catch and wrap the exception into somethin…

I don't think you understand proper exception handling. Catching and wrapping DiskFullException is pretty pointless because what are you going to do about it? Nothing. It's nonsensical for a preferences class to deal with that situation. Instead let it bubble up and so that the caller has the option of handling it, for example by showing a dialog "Delete temporary files and try again?" You'll never be able to catch a…

To your second point: all of these errors should extend IOException ;)

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

#179
post #77

"[Pointers are] arguably the trickiest concept in low-level languages, having no simple real-world analogy[.]" I'm not sure how "address" is not a good, "simple real-world analogy" for pointers. It may be that I've just internalized enough of the behavior of pointers that I'm glossing over important differences, though... I struggled with pointers long enough ago that I don't remember struggling with pointers.

They are so simple. It's just the address of the thing it points to. Maybe it's lost in the mists for me too, but if you don't know your pointers from yout references from your values... how can you code anything?

Based on the experience I've had with teaching programmers, most don't have the distinction clearly in their mental models. For most of basic things they might do it can be made to work either way: usually with a bit of fiddling they can make it work. Of course, this doesn't work at all as soon as you start trying to implement data structures.

I've seen some awkward code too from people moving from Java to C++ where either they make everything a pointer, or they use value objects without understanding that they're not references.

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

#180
post #72

Earlier quoted context omitted.

To make sure you free() all your previous allocations on the way down. You can choose not too, it's "kinda" the same (can't remember the exact difference) but it's dirty and people with OCD just won't accept it. (Disclosure: I got OCD too, this is not meant to make C development hostile to people with OCD.)

If your program is going to exit anyway, there's no need to call free() on allocated memory. The operating system will reclaim all of the memory it granted to your process when it exits. Remember that malloc lives in your process , not the kernel. When you ask for memory from malloc, it is actually doling out memory that you already own - the operating system granted it to you, when malloc requested it. And malloc re…

Multiple reasons.

Some kernels may not get memory back by themselves and expect each application to give it back. We're lucky that the kernels we use everyday do, but we may one day have to write for a target OS where it's not the case. Just hoping "the kernel will save us" is a practice as bad as relying on undefined behaviors.

If you're coding correctly, you have exactly as much malloc()'s as you have free()'s, so when rewinding the stack to exit, your application is gonna free() everything anyway.

Speaking of resources, what about leftover content in FIFOs or shm threads that you just locked?

And when you got OCD, you're only satisfied with this:

    $ valgrind cat /var/log/*
    ...
    ==17473== HEAP SUMMARY:
    ==17473==     in use at exit: 0 bytes in 0 blocks
    ==17473==   total heap usage: 123 allocs, 123 frees, 2,479,696 bytes allocated
    ==17473==
    ==17473== All heap blocks were freed -- no leaks are possible
    ==17473==
    ==17473== For counts of detected and suppressed errors, rerun with: -v
    ==17473== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)
(cat was an easy choice and all I got on this box, but I've had bigger stuff already pass the "no leaks are possible" certification)
Post reply on HN