← Back to context

Comment by antirez

12 years ago

Goto for cleanup is not bad IMHO. I use it extensively...

$ cd redis; grep goto *.c | wc -l 251

All the instances are like:

    goto cleanup;
    goto error;
    goto badfmt;
    goto numargserr;

In this context is easy to read and makes the code structure better.

agreed. Goto's are not bad at all, particularly when dealing with error scenarios. They avoid hack-y if-then error logic (sort of like try/catch/finally)

  • Gotos are bad when used for unconstrained flow control. Restricted use of gotos to implement exception handling is, as you say, not bad.

I don't see the difference between this and

    cleanup(state);
    error(state);

etc.

Just pull them each out into a function. You're still DRY and don't lose flow control.

In my honest opinion, there is never a need for goto.

  • If you are constructing arguments in order, you can destroy them in the reverse order at the exit and this lets you cleanly handle a failure in the middle of allocations:

        thing1 = allocate_thing1();
        if(!thing1) goto cleanup1;
    
        thing2 = allocate_thing2();
        if(!thing2) goto cleanup2;
    
        ...
    
    
        cleanup3:    deallocate_thing2(thing2);
        cleanup2:    deallocate_thing1(thing1);
        cleanup1:    return;

  • Because sometimes the tasks you need to perform cascade, and then you're repeating that cascade all over the place. As I pointed out upthread, check out the Linux kernel: http://lxr.free-electrons.com/source/kernel/fork.c?v=3.3#L42...

    Notice the cascade after the 'out' label; each label after it is for a different level of cleanup needed, depending on how deep into the system call the function encountered the error. Also notice that this is basically the kind of code one would generate for exceptions.

  • In performance critical nested loops, goto is the only way to exit early. A typical example here is performing a matrix multiply. In cases like this, it is absolutely necessary, because C doesn't provide a more granular 'break'.

    • You could leave nested loops with a condition flag, which could produce something semantically equivalent to the goto. It seems like the logic here might be simple enough that the actual check could be eliminated in the generated code by a Sufficiently Smart Compiler (that could actually exist), if there was sufficient demand for it. I'm not sure it's actually more readable, though.

      4 replies →