

Linux Coding Style Guide: GOTOs not always considered harmful. - ma2rten
http://kernel.org/doc/Documentation/CodingStyle

======
Locke1689
They don't really mention it in the style guideline but there are two primary
reasons for using goto in C and they're to make up for two other language
deficiencies.

The first is the lack of exceptions. This is not necessarily a deficiency in
kernel code because it can make other code more complex, but fundamentally
error handling and cleanup usually either requires 1) keeping track of a bunch
of state and then using complicated logic to evaluate the state for error
cases 2) exception catching such that error conditions can be thrown up,
caught, and brought to a cohesive resolution or 3) goto, such that cohesive
cleanup code can be placed together in a segment and then jumped to on error
conditions. (3) is far superior to (1) and, while (2) is arguably superior to
(3), it simply doesn't exist in C.

The second case is that C doesn't have a multi-level break. That is, when in
multiple nested blocks (loops), in order to exit early one would have to keep
track of state and use conditionals to trigger a "waterfall" break all the way
down the block chain. goto solves this by allowing you to jump out of the
chain completely. I think most people would probably agree that adding a
multilevel break (e.g., "break 2;") would probably be preferable to using goto
here, but I think the workaround is basic enough (either use goto or refactor
into separate functions) that the language addition is unlikely now.

~~~
Symmetry
One additional use, which I ran into a few years ago, is to make it explicit
when you're falling through in a case statement.

~~~
kristopolous
I'd like to see an example. Are you familiar with Duff's Device btw?

~~~
Symmetry
An example then:

    
    
      switch( machineState ){
        case ALPHA:
           ...
           break;
        case BETA:
           ...
           goto location;
        case GAMMA:
           location:
           ...
      }
    

No, I wasn't familiar with Duff's device until just now. I'd say that you only
need to be explicit about pointing out fallthroughs if the blocks in the
switch statements are more than a couple of lines long.

~~~
tspiteri
I find that use of goto quite confusing, and would prefer a comment in such a
case:

    
    
        switch( machineState ){
          case ALPHA:
             ...
             break;
          case BETA:
             ...
             /* fallthrough */
          case GAMMA:
             ...
        }

~~~
JadeNB
That's particular to situations that can be solved by fallthrough. What about

    
    
        switch ( machineState ) {
            case ALPHA:
                ... alpha prep ...
                goto gamma
            case BETA:
                ... beta prep ...
                goto gamma
            case GAMMA:
                gamma:
                ...
        }
    

? (EDIT: Not to say that you shouldn't still comment, of course.)

~~~
nitrogen
In this case it might be clearer to just run the switch again after ALPHA and
BETA with GAMMA as the machineState, and if necessary, have logic in GAMMA for
switching machineState back to ALPHA or BETA.

It also might be clearer to move GAMMA outside the switch block entirely:

    
    
        int shouldGamma = 0;
        switch ( machineState ) {
            case ALPHA:
                ... alpha prep ...
                shouldGamma = 1;
                break;
            case BETA:
                ... beta prep ...
                shouldGamma = 1;
                break;
            case GAMMA:
                shouldGamma = 1;
                break;
        }
        if(shouldGamma) {
            // GAMMA stuff here
        }
    

The shouldGamma flag would be unnecessary if all possible values for
machineState should still run the code in GAMMA.

------
schlomie
Gotos were traditionally discouraged to students since they would write code
that was needlessly hard to follow (and buggy as a result), so instructing
them to not use gotos improved the readability of their code and improved
their thought processes.

That being said, Richard Stevens, a respected author on Unix programming, had
this to say:

<http://www.kohala.com/start/rstevensfaq.html> Q: Why do your programs contain
gotos?

Read Structured Programming with go to Statements by Knuth in the ACM
Computing Surveys, Vol. 6, No. 4, Dec. 1974 issue. (In fact, this entire issue
of Computing Surveys is a classic.) My challenge to the goto-less programmer
is to recode tcp_input() (Chapters 27 and 28 of TCP/IPIv2) without any gotos
... without any loss of efficiency (there has to be a catch).

------
16s
Young programmers hear that goto is bad and should never be used. They begin
repeating this to others. Then the whole world thinks goto is bad, because 99%
of devs say so.

Then an expert, highly-regarded dev shows code that has useful goto
statements. And only 1% of coders understand that this is perfectly
acceptable. They know that goto is not evil (all the time) and is even very
useful in certain cases.

~~~
5hoom
I think just the tiniest bit of experience with assembly would chase away a
lot of unwarranted fears about goto.

At that level it's all goto so you have to use them. And if you don't want
your program to become a spaghetti nightmare you have to use them wisely.

When using anything higher level you can & should use 'if', 'for', 'while',
etc. but it's not like the world implodes if you use a goto in your code.

------
nhebb
I wish I had a link, but I recall reading that Dijkstra said the backlash
against goto's was overblown. You hear the same kind of dogma repeated about
globals, multiple points of return, and others. It's not that these constructs
should _never_ be used, it's that they should be used judiciously.

------
cpeterso
If coding without goto statements makes code flow easier to understand,
consider taking the next step and coding without if() statements!

Many conditional statements and sentinel null values can be replaced with
strategy objects or mock objects, revealing a more functional programming
style that can make testing easier.

<http://programmingwithoutifs.blogspot.com/>

------
tmhedberg
Goto statements are so widely shunned that for a long time, I didn't even
realize that C had one. It wasn't until I started reading some Linux code that
I found out that it existed.

At first I was more than a little bit turned off by the practice, but once I
understood _how_ it was being used, it made a lot of sense. The bottom line
is, goto statements which jump backwards are generally Considered Harmful.
Goto statements which jump forwards, within a limited scope, and used
conservatively, can serve to improve the readability of code.

I still almost never use them, but now I know when it would be appropriate to
do so, rather than dogmatically rejecting the entire practice. I think the
idea that gotos are always bad is one of those things that programmers tend to
accept as "received wisdom", without considering the actual motivation for the
principle, or in which cases it might not apply as strongly.

~~~
scott_s
The Linux kernel does not just use gotos to "jump forwards." If you look
careful, they've implemented a simplified version of try-catch-finally. It's a
structured use of gotos, implementing clear semantics.

~~~
tmhedberg
I didn't mean to suggest that Linux kernel gotos were just arbitrary forward
jumps. I know that they are used for error handling. That's the legitimate
usage I was alluding to, I just wasn't specific about it.

------
mrj
In C with it's lack of exceptions, goto can be used to jump unconditionally to
cleanup code before exiting a function. This is _far_ cleaner than every
branch and loop following a call needing explicit instructions to check for
error statuses, sometimes multiple errors (like malloc something, check for
error, use dynamic memory in a call, check for a different error).

It's also more maintainable, since the error checking is done in a single
place and a single jump. Without a goto, if there were a new error condition
to check, it might take several updates to ensure all error conditions are
accurately checked.

Generally, gotos for handling exceptional cases _inside a function_ : okay.
Goto for implementing twisted logic: bad.

------
atilimcetin
Linus about the use of goto's (and Pascal):

I think goto's are fine, and they are often more readable than large amounts
of indentation. That's _especially_ true if the code flow isn't actually
naturally indented (in this case it is, so I don't think using goto is in any
way _clearer_ than not, but in general goto's can be quite good for
readability).

Of course, in stupid languages like Pascal, where labels cannot be
descriptive, goto's can be bad. But that's not the fault of the goto, that's
the braindamage of the language designer.

<http://kerneltrap.org/node/553/2131>

------
spaghetti
goto is useful for breaking out of 2+ nested loops early.

------
jk-in
goto is very useful in device drivers, especially in functions that require
clean up (e.g., freeing memory) in case an error is detected.

