Using goto for error handling in C

April 27th, 2009 at 6:38 am

Introduction

We would all like to write nice and clean code, with cute little algorithms and crystal-clear structure, without giving much thought to the often ugly topic of error handling.

But unfortunately in programming, perhaps more than in any other kind of engineering, the devil is in the details. The handling of errors and of irregular inputs and data usually requires more code than the straight-line algorithm for solving the problem itself. This is a regrettable but unavoidable artifact of our craft.

But wait, there’s more. As difficult as error handling is, coupled with resource allocation and the need for robust deallocation it is nothing short of a huge headache. Fortunately, in newer high-level languages this is less of a problem because of automatic garbage collection. Also, C++ provides tolerably robust solutions in the form of RAII. But as the title states, here I’m concerned with C, which doesn’t have exceptions and destructors, so the issue is much more difficult.

In this article I will argue that the much hated goto statement is a valuable tool for simplifying error-handling code in C.

A simple case

Here’s a quote from the Wikipedia article on RAII:

C requires significant administrative code since it doesn’t support exceptions, try-finally blocks, or RAII at all. A typical approach is to separate releasing of resources at the end of the function and jump there with gotos in the case of error. This way the cleanup code need not be duplicated.

The code sample the article shows is this:

int c_example()
{
    int ret = 0; // return value 0 is success
    FILE *f = fopen("logfile.txt", "w+");

    if (!f)
        return -1;

    if (fputs("hello logfile!", f) == EOF)
    {
        ret = -2;
        goto out;
    }

    // continue using the file resource
    // ...

    // Releasing resources (in reverse order)
out:
    if (fclose(f) == EOF)
        ret = -3;

    return ret;
}

Sure, by inverting the logical comparison, this can be rewritten without a goto as follows:

int c_example()
{
    int ret = 0; // return value 0 is success
    FILE *f = fopen("logfile.txt", "w+");

    if (!f)
        return -1;

    if (fputs("hello logfile!", f) != EOF)
    {
        // continue using the file resource
    }
    else
    {
        ret = -2;
    }

    if (fclose(f) == EOF)
        ret = -3;

    return ret;
}

Although we’ve gotten rid of the goto, IMHO this code isn’t much cleaner. Note that we’ve just moved the mainline code into a condition. Will we do it for any error condition the function encounters?

A thornier case

Now consider this snippet:

int foo(int bar)
{
    int return_value = 0;

    allocate_resources_1();

    if (!do_something(bar))
        goto error_1;

    allocate_resources_2();

    if (!init_stuff(bar))
        goto error_2;

    allocate_resources_3();

    if (!prepare_stuff(bar))
        goto error_3;

    return_value = do_the_thing(bar);

error_3:
    cleanup_3();
error_2:
    cleanup_2();
error_1:
    cleanup_1();
    return return_value;
}

How would you get rid of the goto here, without duplicating the cleanup code or complicating it considerably? Following the logic of our previous goto hunt, we could use nested conditions:

int foo(int bar)
{
    int return_value = 0;

    allocate_resources_1();

    if (do_something(bar))
    {
        allocate_resources_2();

        if (init_stuff(bar))
        {
            allocate_resources_3();

            if (prepare_stuff(bar))
            {
                return_value = do_the_thing(bar);
            }

            cleanup_3();
        }

        cleanup_2();
    }

    cleanup_1();

    return return_value;
}

But look where our mainline code is now – deep inside the nested conditions. And keep in mind this is still a simplified example – each of the allocations, checks and code chunks could be significantly larger. Is that really any help for the readability?

No, goto is better here. It results in a more readable code, because the operations the function performs are structured in a logical order – errors get thrown somewhere else, while the mainline code goes on where it belongs. In the nested conditionals version, it’s outright hard to find where the main code is, buried inside the error checks.

By the way, there’s an even more complex case with various resources presented here. And using goto for the purpose of error handling is a common idiom in the source code of the Linux kernel, so that lump of code contains lots of examples as well.

Additional valid uses

Besides the point made above, goto is also sometimes (though much less frequently) useful for breaking out of deeply nested loops. If your algorithm requires a nested for loop (say, 4 levels deep), and in the innermost loop you sometimes encounter a special case that should cause you to break out all the loop levels, do use a goto. The alternative of creating exit flags at each level and checking them in each iteration requires much more code, is uglier, harder to maintain and is much less efficient (nested loops tend to appear in tight algorithmic code that needs speed).

A note on C++

In C++ you don’t need goto for clean error handling. Exceptions and adherence to RAII are much better for that.

Sources

Here are some interesting sources on this topic:

  1. A newsgroup discussion from comp.lang.c
  2. "Structured programming with go to statements" – an article by Donald Knuth (google it)
  3. This stackoverflow discussion.
  4. Proggit thread
  5. Chapter 2 of the Linux Device Drivers book
  6. Linux kernel mailing list discussion
  7. RAII in C
  8. Wikipedia entry on RAII

Related posts:

  1. Good Goto (TM)
  2. “Unassigned variable” error in C#
  3. Robust exception handling
  4. Handling out-of-memory conditions in C
  5. Computed goto for efficient dispatch tables

30 Responses to “Using goto for error handling in C”

  1. ripper234No Gravatar Says:

    I agree. We’ve all been taught that “goto is evil”, but those teachers missed to point out where it’s useful.

    For comparison, here is a piece of code I saw yesterday, with a bad usage of goto:

    void foo()
    {
    
    ...
    
    goto end:
    ...
    
    end:
    }

    The goto here can just be replaced with a return.

  2. Jussi JumppanenNo Gravatar Says:

    In most cases code can be restructured to not require the uses of a goto statement.

    For example here is your c_example written without a goto statement:

    int c_example()
    {
        int ret = 0; // return value 0 is success
        FILE *f = fopen("logfile.txt", "w+");
    
        if (f)
        {
            if (fputs("hello logfile!", f) == EOF)
            {
                // continue using the file resource
                // ...
            }
            else
                ret = -2;
    
            // Releasing resources (in reverse order)
            if (fclose(f) == EOF)
            {
                ret = -3;
    
                // or this if the first return value is needed
                ret = (ret == 0) ? -3 : ret;
            }
        }
        else
            ret = -1;
    
        return ret;
    }
  3. MobbitNo Gravatar Says:

    And why didn’t you use a function for this? int errorHandling() { … return x;} you could even pass the error-type as a int-constant or a string and switch through the cases as you did in the goto.

  4. C-KeenNo Gravatar Says:

    @Mobbit:

    This would mean that you also have to hand all state to the error handling function which does not seem to make the code any cleaner…

  5. Pádraig BradyNo Gravatar Says:

    Note for the common case of a common cleanup, one can:

    void foo()
    {
    do {
    if (!do_something(bar)) break;
    if (!do_something_else(bar)) break;
    return;
    } while(0);

    cleanup();
    return;
    }

  6. buritoNo Gravatar Says:

    @Mobbit & Mr Brady

    Sorry guys, but you are arguing against Donald Knuth on the subject of programming, ergo you lose. Badly. And you have to clean up the mess. Before you go home.

    Go do some research, find reference number 2. It’s not a link because this paper pre-dates the internet. That is how far behind you are for not knowing about this.

  7. Patrick SimpsonNo Gravatar Says:

    I agree that this is a valid use of a goto; perhaps even the only valid use. I use this fairly recently, but to avoid confusing control flow I always limit myself to 1 label at the end of the method. So rather than

    error_3:
        cleanup_3();
    error_2:
        cleanup_2();
    error_1:
        cleanup_1();

    I would write:

    error:
        if (allocated_3) cleanup_3();
        if (allocated_2) cleanup_2();
        if (allocated_1) cleanup_1();

    where allocated_ is some means to detect if the allocation worked, generally just a pointer check.

  8. qNo Gravatar Says:

    This is terrible.

    If you were to use goto’s in embedded programming, you are put against the wall without any further consideration. Besides, using multiple returns in one function will yield an equal result.

    A goto in your simple examples might look good; a goto on the more complex examples you don’t provide might look good too, but is simply disguising the fact you’re being a bad/lazy module designer.

    And if you were not to program in C for an embedded environment, why not just use C++/Python/whatever? (Ok, legacy code.)

    Just don’t use goto. Now go out and play.

  9. cwccNo Gravatar Says:

    I think the main reasons against goto aren’t relevant yet because in general we haven’t matured enough as programmers.

  10. thomasNo Gravatar Says:

    Goto is considered harmful. Do they teach nothing at universities these days?

  11. JohannesVonLuckNo Gravatar Says:

    For those of you who blatantly cry foul at the use of goto in fashions such as this article describes, I would like to point out that there may come a time in your life where you have to think for yourself for once. Grow up, people. There are times where the usage of certain “bad things”, such as goto, make sense for what you’re doing. Does this mean we shouldn’t still be careful of such traps? Absolutely. Simply put, use the right tool for the right job. If a goto is readable, adds to reducing coding time, then use one. Good coders know that there is only ONE always: it’s always is a matter of situation.

  12. JohannesVonLuckNo Gravatar Says:

    And to those of you who still cry foul and refuse to see your zealotry any other way:

    goto hell; /* stick this in your pipe and smoke it */

  13. elibenNo Gravatar Says:

    @g,

    How can multiple returns help me in this situation? Can you provide a code snippet that demonstrates it? Besides, multiple returns in a function are frowned upon no less than gotos.

    And I do happen to program embedded devices in C. No one “puts you against the wall” for judiciously using a construct in a controlled manner that makes your code cleaner. Trust me on this one.

  14. MikeNo Gravatar Says:

    Programming well, with a logical flow of control can be done well
    with or without gotos. I would use them if needed, and not otherwise.
    The mantra against gotos is mostly given to those who can not make
    a reasonable distinction on when to use them. For those programmers -
    NO GOTO!

    But, I find that programmers who would likely misuse goto just
    find something else to misuse, so I’m not sure it matters much
    in the end.

    Mike

  15. ripper234No Gravatar Says:

    “multiple returns in a function are frowned upon no less than gotos”

    Not bloody likely. Multiple returns are useful and common. There is some debate on them, true, but there isn’t anywhere near a near-total consensus like for goto.

  16. kifNo Gravatar Says:

    Interesting read. I’ve used goto in embedded systems for error handling, and the only other use I can think of is breaking out of a deeply nested set of loops without using an error flag at every level of iteration.

    I try to avoid multiple return statements — especially if they’re towards the middle of the function. Sometimes I’ll have 2 or 3 very simple error checks at the top of a function that return immediately (just abort and return error). My returns are at the beginning or end of a function… never in a nested if-else in the middle of the function.

  17. Daniel MartinNo Gravatar Says:

    Hi, nice article, should cause a few people to actually engage their brain which can only be a good thing. Personally though I think I still prefer to have lots of nested IFs. It just doesn’t feel too ugly to me. But hey, maybe this will fetser in the back of my mind and take over eventually!

    (I don’t even like exceptions that much.. – I guess I’m a bit sick.)

  18. TwyliteNo Gravatar Says:

    The general injunction against “goto” and multiple returns comes from a particular school of structured programming (Dijkstra) that shows that you can prove less about a program when you allow such flow control options. This doesn’t make them wrong – the programs may have fewer provable qualities, but may at the same time be more readable and thus more maintainable.

    Oh, if you’re avoiding goto and multiple returns because of Dijkstra’s “goto considered harmful”, then you’d better stop using exceptions too — they violate his structural rules.

    A do/while with breaks to jump to a cleanup section is a dirty hack to avoid using goto. It keeps the structuralists happy because it doesn’t technically violate their rules, but it is _more dangerous_ than goto. Didn’t know that, did you? The C standard does not define semantics for break/continue in nested loops, so you cannot (safely, across compilers) use looping constructs within your error handling do/while construct.

    Fortunately Knuth (who unlike Dijkstra DID program) wrote “Structured Programming with Goto Statements” and dispelled the idea that goto is always bad … or at least he would have if people could grasp the idea of not pushing Dijkstra’s goto myth all the time …

  19. Star brightNo Gravatar Says:

    The idea of structural programming is to have

    * one point of entry in a block of code
    * and one point of entry out.

    As well as goto’s, the following violates this idea

    * multiple returns
    * expection handling
    * breaks
    * continue

    In the author’s examples, there is one point of entry into the function and one point of entry out. His goto’s stay within the function.

  20. qNo Gravatar Says:

    @elibenSays
    Multiple returns are made by the devil too. Using it yields an equal result: you will be put against the wall as well.
    Well actually, you’re right, we stopped shooting people a while ago. We use peck and feathers now.

    If your code is to be MISRA compliant, must pass a pretty severe QA-C test, and needs 100% test coverage on all decisions in your code, you better not use goto, or multiple returns (a.o.)

    About that “judiciously using a construct”, I understand you. But do also know that consistency has to be taken in account.

    For Christ’s sake, what am I arguing here? What will be defended next? Basica rules?

  21. qNo Gravatar Says:

    Now I come to read Twylite’s comment,
    yes, a break inside some loop is a third way to ensure the ordering of new fresh peck and a set of feathers.

  22. kifNo Gravatar Says:

    @g, I’d never heard of MISRA but upon reading their mission statement:

    “To provide assistance to the automotive industry in the application and creation within vehicle systems of safe and reliable software.”

    I’m pretty damn glad they exist ;) .

  23. xNo Gravatar Says:

    I’m way late to the game, but in the spirit of being a smart ass….

    “The classics are books everyone has heard of but noone has read”

    seems apt.

    What do you think a while loop does, if not a “hidden” goto:

    while( condition() ) {
    do_this();
    }

    /* versus: */

    do_this_loop:
    if ( condition() ) {
    do_this();
    goto do_this_loop;
    }

    If you’re gonna bitch about gotos, isn’t it hypocritical and completely “head in the sand”-ish to use while loops? Why are you using processors with JMP instructions? Please show me this new computer of yours that works differently.

    Assuming you choose a good label name, don’t gotos better promote “self-documenting code” ?

    Jussi JumppanenNo Gravatar Says:
    April 27th, 2009 at 08:26

    In most cases code can be restructured to not require the uses of a goto statement.

    Jussi: Why? Why do *you* think goto is bad and that is necessary?
    Because other people told you it is bad?

    Pádraig BradyNo Gravatar Says:
    April 27th, 2009 at 10:33

    Note for the common case of a common cleanup, one can:

    Pádraig: I fail to see how this is any clearer, and it is harder to decipher what is really going on. Again, no justification given to why one would want to do this.

    qNo Gravatar Says:
    April 29th, 2009 at 09:19

    If your code is to be MISRA compliant, must pass a pretty severe QA-C test, and needs 100% test coverage on all decisions in your code, you better not use goto, or multiple returns (a.o.)

    If whatever tool(s) you use can’t determine when all the paths in your code are taken when you use gotos or multiple returns(), isn’t that more a problem of the tool you are using, or maybe the fact you are using C when you should be using something else?
    Why can’t that tool “parse” or work with valid C code?

    I realize limiting yourself to a subset of C is a very good thing in certain cases, especially in regards to “proving” things about code.

    Are you saying you *would* use multiple returns and gotos on code that did not need to be ran against those particular tools / QA processes?

    My understanding is the QA and test coverage is a job requirement, but that makes your argument less valid to me — you are only against goto because your job won’t let you use them.

    I am in favor of multiple return statements. If you know the “answer” to a function, why dilly-dally, instead of return it immediately, as soon as you know?

    Sure, you can use nested ifs, but that makes for hairy hard-to-follow code, and huge indention leads to things not fitting on a single screen (whether vertically or horizontally) of your editor.

    Comments? I hope my self-righteous tone is enough for some posters here to realize theirs. Do some people really expect we should believe them because their name is attached? Or someone else said so? And nary a word of *why* they feel the way they do, and what brought them there?

    Yeah, I like to debate about things that might not matter, but if you didn’t want a debate, why did you post on this topic? Or why did you post on a topic you don’t care about?

    I am not the perfect person or coder by far. But I think a good person is thinking for themselves and not repeating what they are told, *especially* when it comes from the “mouths of the gods”, be it coding or whatever.

    (yes, I will take some chill pills).

    Sorry, I can only hope Djikstra had good intentions and would have been happy his message “got out” eventually. But I also hope he would have utter shock and disbelief at how many people swallow it now w/out a second thought.

  24. emacsNo Gravatar Says:

    I often use
    do {
    ….
    } while(0);

    error handling

    instead of goto

  25. Ram DobsonNo Gravatar Says:

    I think i would still use ifs here, and if things got too deep, like in the second example i’d do something like this

    `function foo {

    var1 = allocate_stuff();
    if ( !next_foo(bar)) {
    cleanup_1();
    return 0;
    }
    return do_the_right_thing(bar);
    }

    and do the inner stuff in the next_foo function.

    now i can already see that this doesn’t pass all the state in to the second function,
    but seriously… do you want to maintain the giant mess of code that is one function
    where everything is passed implicitly from the parent scope? i didn’t think so.

    if next_foo depends on var1, then next_foo(bar,var1) it makes it clear that the remainder depends on var1. much nicer, and next_foo will be clear.

    i’m sorry, but your argument that the second version looks ok now, but if it was a giant mess, it would be messy, just doesn’t ring true. If the function was a mess, then you’ve got too much going on in one function… and breaking out goto isn’t gonna make that turd any shinier.

    In your version of the big messy function the creation and cleanup of thing1 are like miles apart, on opposite ends of a giant mess, connected by a goto… ick.

    compare that with my version, a small tight function, which creates something, has calls out to “try_to_continue” (next_foo) and cleans up if that fails.

  26. Ram DobsonNo Gravatar Says:

    and oh, i can see the point about not blindly avoiding goto, and if the multiple returns upset some people, you could do the same thing like this:

    function foo {
    
    var1 = allocate_stuff();
    result = 0;
    if ( !next_foo(bar)) {
      cleanup_1();
    } else {
      result = do_the_right_thing(bar);
    }
    return result
    }

    and i should admit that i am offering *3* tight functions to replace one messy one, which is a less clear advantage, but in my book, still quite preferable.

  27. David MoránNo Gravatar Says:

    From Linux kernel documentation (in the file “Documentation/CodingStyle”)

    Chapter 7: Centralized exiting of functions

    Albeit deprecated by some people, the equivalent of the goto statement is
    used frequently by compilers in form of the unconditional jump instruction.

    The goto statement comes in handy when a function exits from multiple
    locations and some common work such as cleanup has to be done.

    The rationale is:

    - unconditional statements are easier to understand and follow
    - nesting is reduced
    - errors by not updating individual exit points when making
    modifications are prevented
    - saves the compiler work to optimize redundant code away ;)

    int fun(int a)
    {
            int result = 0;
            char *buffer = kmalloc(SIZE);
    
            if (buffer == NULL)
                    return -ENOMEM;
    
            if (condition1) {
                    while (loop1) {
                            ...
                    }
                    result = 1;
                    goto out;
            }
            ...
    out:
            kfree(buffer);
            return result;
    }

    And when I count gotos in the linux kernel (2.6.34):
    hidark@gentooza /usr/src/linux $ grep -E "goto.*?;$" * -R | wc -l
    76825
    hidark@gentooza /usr/src/linux $

    Wow, 76825 gotos… Interesting, as you know, there are many embedded devices that are using Linux (as android, or maemo). I think goto is an available tool, I don’t use it often but in some cases could be useful and could improve the code readbility.

  28. elibenNo Gravatar Says:

    @David,

    Interesting – thanks!

  29. JopeNo Gravatar Says:

    Hi,

    for some hilarious comments from Linus Torvalds on gotos in the Linux kernel,
    check out this: http://kerneltrap.org/node/553/2131

  30. DmitryNo Gravatar Says:

    There is a another way to avoid gotos in contruction/rollback code.
    We created a set of macros that hides details of initialization failure handling and rollbacks and allows to write straightforward code like:

    CONSTRUCT_STEP(step1, init_step_func1(…))
    CONSTRUCT_STEP(step1, init_step_func2(…))
    CONSTRUCT_STEP(step1, init_step_func3(…))
    .
    .
    .
    ON_FAILURE(destruct_func())

    Macros track steps succeeded and performs proper rollback without touching uninitialized parts.
    Also it catches forgotten cleanups and improper order.
    Moreover it allows to simulate failure of each step and verify rollback correctness.
    There are a lot of macros’, but code is excellently readable and error-proof

    Check CStart library (free and open source):
    http://www.daynix.com/index.php?option=com_content&view=article&id=62&Itemid=71
    https://github.com/daynix/bricklets/wiki/CSteps-bricklet-documentation