Live data from Hacker News

How can C Programs be so Reliable? (2008)

tratt.net

221–230 of 230 posts

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

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

Exceptions are kind of like gotos, but worse, because the jump target is decided at runtime based on the state of the call stack and therefore cannot be determined just by looking at the code. So they're more like comefroms [0] than gotos. [0] http://en.wikipedia.org/wiki/COMEFROM

> So they're more like comefroms than gotos.

Except, not, because the jump source for a particular exception handler is no more (and no less) determinable in advance than the jump target of an exception raised at a particular point. They are very much unlike either gotos or comefroms.

If you are going to criticize exceptions, do it directly, rather than by asserting that they are like something that they are completely unlike.

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

#222

Earlier quoted context omitted.

In a lot of ways, comparing syscalls like stat and Java methods is apples and oranges. System calls are at the very bottom of the stack, where userspace interacts directly with kernelspace, so they must return all error information, otherwise there would be no other way to get it from userspace. So it's not really examplary of C language style that syscalls behave this way. Syscalls are not designed to obscure what's…

It's no longer even true that the kernel returns all error context; for example selinux is supposedly a nightmare to figure out "why was this denied?".

Maybe that's because SELinux was handled by the NSA, and they're not so thorough?

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

#223
post #213

Earlier quoted context omitted.

That might be what they are intended to be reserved for but the reality of what they get used for is much more of the "Jump Somewhere" sort.

Really? I had it drilled into me from day 3 or so, that "EXCEPTIONS ARE NOT FLOW CONTROL!"

After more than a decade of seeing exceptions in use it has become very apparent that no matter what they might have been told when they learned about exceptions most people use them for flow control. Mostly because they are a way of doing flow control.

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

#224
post #218
post #208

Earlier quoted context omitted.

Can you really tell me that you know after an exception that the other threads are really in a well-defined state let alone 'perfectly valid'? Look at something like ZeroMQ that is being rewritten specifically to avoid the non-determinism inherent in throwing an exception. Once you're using threads it's pretty much anyone's guess as to what state the system is in at any point, add exceptions and it just gets worse.

An exception in one thread shouldn't affect others - why would it? I agree that unstructured use of threading primitives leaves you with an unpredictable system, but it's possible to build safer, higher-level abstractions and use those.

Because fundamentally the only reason to use threads rather than fork is to share memory. If an exception leaves shared memory in an undefined state then all threads that share that memory are in undefined states.

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

#225

Earlier quoted context omitted.

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…

First, you sometimes do want to call exit deep within a program. That is the situation I am addressing, not normal operation. Of course you want to always free unused memory and prevent memory leaks. I am quite familiar with the importance of memory hygiene, and have even written documents admonishing students to use valgrind before coming to me for help: http://courses.cs.vt.edu/~cs3214/fall2010/projects/esh3-debu..…

They say memory is the second thing to go. ;) Unfortunately, the OS doesn't know how to remove files or modify database entries that also represent program state, or properly shut down connections to other machines. Proper unwinding is still necessary.

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

#226
post #200

Earlier quoted context omitted.

>> I am not suggesting any nesting of anything. Repeatedly checking at the same indentation level. This could be considered wasteful. You end up checking if something is NULL, if it is you jump to the cleanup code and immediately check again. Nesting may be more elegant. >> What matters more to you, getting stuff right or repeating adages that other people have said out of context? `goto` is probably the cleanest way…

> This could be considered wasteful. It's true that there is an extra compare. I think it's a small cost for maintainable code. > Then they need to read what the function is doing and understand it before they mess with the code, just like in any other situation. Sounds great, however, the time they spent figuring out your haphazard, repetitive and confusing free() statements could be better spent somewhere else. Whe…

>> It's true that there is an extra compare. I think it's a small cost for maintainable code.

And I don't think it's the only way to achieve maintainable code. That's all I'm saying.

>> Sounds great, however, the time they spent figuring out your haphazard, repetitive and confusing free() statements

If it's the coding standard of the product that you have a small block of this at the top before you start actually writing the function then it doesn't take any more time for a coder to understand than any other way around, the important part is consistency.

>> I advocate them because I have seen them work really well and I have seen yours create mounds of inflexible spaghetti.

What's mine? I'm not advocating any of them, just sticking to one. I still don't think yours is any better than (for instance) -

    type function()
    {
        type2 *thing = (cast) malloc (size);
        type2 *thing2;

        if (thing)
        {
            thing2 = (cast2) malloc (size2);
            if(thing2)
            {
                // do some stuff here
                // and some more stuff
                ...
                free(thing2);
            }
            free(thing);
        }
        return code;
    }
A pattern which auto-unrolls as it exits without the need for more tests, and to me is every bit as maintainable as the goto cleanup; pattern.

Spaghetti code (to me) is more about encapsulation and modularisation failures than it is about the content of any individual function.

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

#227

Earlier quoted context omitted.

First, you sometimes do want to call exit deep within a program. That is the situation I am addressing, not normal operation. Of course you want to always free unused memory and prevent memory leaks. I am quite familiar with the importance of memory hygiene, and have even written documents admonishing students to use valgrind before coming to me for help: http://courses.cs.vt.edu/~cs3214/fall2010/projects/esh3-debu..…

They say memory is the second thing to go. ;) Unfortunately, the OS doesn't know how to remove files or modify database entries that also represent program state, or properly shut down connections to other machines. Proper unwinding is still necessary.

For the third time, I specifically addressed resources that are not controlled by the operating system.

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

#228
post #173
post #86

Earlier quoted context omitted.

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.

I also find it very disingenious of the pro-exceptions post to claim that these mazes of ifs are easy to navigate. In his example that is sort-of true. When you're using actual real data to make the comparison it's easy to introduce very hard to trace bugs in them.

Once I had two things to check, one being time, and as you know that means 8 cases. You have to pick one to check first, and I picked the non-time based check to check first. That means that I suddenly didn't check all cases anymore :

  if (currentTime()  lowerBound) {
        // at this point you of course do NOT know for sure that currentTime 
(these look like they can be trivially merged. That's true if you look at just these lines, it becomes false if you look at the full set of conditions).

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

#229
post #226

Earlier quoted context omitted.

> This could be considered wasteful. It's true that there is an extra compare. I think it's a small cost for maintainable code. > Then they need to read what the function is doing and understand it before they mess with the code, just like in any other situation. Sounds great, however, the time they spent figuring out your haphazard, repetitive and confusing free() statements could be better spent somewhere else. Whe…

>> It's true that there is an extra compare. I think it's a small cost for maintainable code. And I don't think it's the only way to achieve maintainable code. That's all I'm saying. >> Sounds great, however, the time they spent figuring out your haphazard, repetitive and confusing free() statements If it's the coding standard of the product that you have a small block of this at the top before you start actually wri…

So you avoid a few null checks but you introduce the indentation problem you mentioned a few comments ago.

I think we can agree this is better than the alexkus example but there are tradeoffs involved.

(PS: I am bothered at how you cast the return value of malloc, this is C we're talking about right, not some other language with more plus signs? :-))

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

#230
post #224
post #218

Earlier quoted context omitted.

An exception in one thread shouldn't affect others - why would it? I agree that unstructured use of threading primitives leaves you with an unpredictable system, but it's possible to build safer, higher-level abstractions and use those.

Because fundamentally the only reason to use threads rather than fork is to share memory. If an exception leaves shared memory in an undefined state then all threads that share that memory are in undefined states.

True, but why would an exception ever leave memory in an undefined state? I can imagine it corrupting a thread's own stack in some languages, but you wouldn't use a thread's stack for shared memory (at least, not without some construct that told other threads when it was safe to access it)
Post reply on HN