Hacker News new | comments | show | ask | jobs | submit login
If goto statements are bad why does linux src have more than 10k of them? (github.com)
31 points by ilovecookies on Dec 17, 2014 | hide | past | web | favorite | 45 comments

Contrary to popular reputation, there are a handful of use cases where "goto" makes the code simpler, cleaner, more readable, and (in rarer cases) faster. In these cases, you should use goto statements. A good programmer can recognize these cases and use goto appropriately. Goto is never necessary in a strict sense but occasionally it can eliminate some pretty ugly spaghetti code.

The use cases for goto I see are primarily complex/thorough error handling (e.g. unwinding some concurrency control mechanisms) and certain low-level state machine patterns. I would expect to see these kinds of use cases in the Linux kernel.

And C doesn't have exceptions, which otherwise would cover a lot of where goto's are used.

There is a difference though. Exceptions can result in Stack Unwinding which is costly. Gotos are a jump which costs literally nothing.

In practice you will do the same thing as unwinding the stack. You'll jump to the end of a function where you'll likely free some heap buffers on your way out and you'll return error status to the caller. What will likely happen next is the caller will bubble up the error: free buffers and report error status to their caller. It works out to pretty much the same thing as a modern C++ code base using RAII, just more manual.

It does have longjmp, which can do basically the same, just without safety (surprise!)

Seems like they use it for most of the error handling, that's true. Almost as many of these as there are switch statements (and 1/3 of if statements). It would be cool if someone could analyze keywords from different projects. Maybe one could give that as use cases in universites instead, that would seem to be alot more practical.

EDIT: Upon closer inspection it seems like even if 'gotos' make everything nastier the extra added performance is worth it.

As long as they're local I guess, like a handmade `finally` clause. It's like mutation in functional programming languages, they're allowed as long as they don't leak. IIRC Zed Shaw's Learn C the Hard Way has some nice `goto` examples..

Breaking from nested loops with goto is also cleaner and simpler. Which is actually one of the reasons some higher level languages even have a goto statement.

For that use-case in particular, a "labeled break" is an alternative that some languages use (like java). I somewhat semantically prefer it if given the choice (name the loop being broken, vs. naming the end-point to jump to), though that preference isn't strong.

Ah yes, the "good" programmer that is well versed in when goto statements are warranted.

The original context of the "GOTO considered harmful" is lost on most of us, as at the time there were large swaths of developers that were trained before structured programming took off, so people were using global variables and GOTOs instead of procedures and functions. GOTO has its place, specially in C.

It is sinful to jump into a different function and pass around information as global state. GOTO as functionality is tangential in this matter.

Growing up in the 80s, that's how a lot of books taught us BASIC, because they catered to a lowest-common-denominator implementation. Fortunately, I was using BBC BASIC, with functions, procedures and REPEAT-UNTIL (and later WHILE and CASE), and the BBC-specific books taught structured programming.

On error GOTO next

The empty catch block of BASIC.

For every line of code (just to be pedantic).

I have customers still churning out wads Classic ASP who think On Error Resume Next magically fixes their shabby code. Makes me weep.

> It is sinful to jump into a different function

I've heard of that. It's called "exceptions", right?

I find it kind of amusing when people are afraid of "goto" but not "throw", "break" or "return".

You skipped the "and pass information around as global state" part. It obviously depends on your language, but ideally an Exception object should be a specific class you can choose to catch or re-raise, and it should include a message. None of the calling state should be visible to you.

I give you that I skipped it. I skipped it intentionally to make a bit of hyperbole.

An exception is still essentially a goto that crosses stack frames. There is a whole class of common bugs, you will see a lot of talk of them in the C and C++ communities, where an early return or a throw at an unexpected time leads to resources not being cleaned up. A lot of good coding styles say avoid this stuff, it's dangerous, and they are not without cause. Whereas a goto cleanup block is often a lot more explicit and therefore can lead to more reliable code than a scheme that encourages not sweating details and not expecting failure at every step.

>It is sinful to jump into a different function

So sinful you can't in C

You can do it in GNU C! It's used to write direct-threading interpreters.


They don't intend for label addresses to be gone to outside of the function they are located in. The stack wouldn't be setup to handle them at all.

Sure, you can store them wherever, and do something like " goto *g_greenthreads[ threadno ].lastpos ", but you would call that within the function defining the label, not outside it.

From your own link: > You may not use this mechanism to jump to code in a different function. If you do that, totally unpredictable things will happen. The best way to avoid this is to store the label address only in automatic variables and never pass it as an argument.

I assumed the parent poster meant back before functionality was expressed as functions; i.e. it's sinful to jump from functionality A to functionality B if it's not expressed in terms of packaged functions, and impossible to do so if it is.

With longjmp you can. Your stack will be trashed, though, so any state better be global!

Dogmatically following so called rules in a cargo cult programming style without any understanding of the rationale behind them is many orders of magnitude more bad.

This form of blind programming is terribly dangerous. It takes focus away from the task and placed on the process.

Engage with the problem, engage with the computer. Do not engage with autocratic decrees and programming equivalencies of heretic and kosher.

Goto does something specific. If you need that specific thing then that's why it's there. Ceremonial rituals be damned

At a glance, looks like most of 'em are used for error handling. Sort of a `try ... finally` for C. This is actually a fairly common pattern -- check out Python's source code for more examples.

The other way I've seen it used is to break out of multiple levels of nested loops, though that's far less common.

`goto` is bad when it's used in an unstructured way: e.g. A does some stuff, then `goto B`. Then B does some stuff, then `goto C`. C sets a flag, does more stuff, then `goto B`. B does something different this time around based upon the flag set by C. Jumping around in a completely uncontrolled way such that the code can't be comprehended is where goto is "bad".

goto isn't inherently bad, it's just easy to use it in bad ways (and once upon a time, people did so more so than they generally do today -- which iirc was Dijkstra's major beef with it)

Linus himself has publicly said he doesn't mind appropriate gotos. "I think goto's are fine, and they are often more readable than large amounts of indentation." Mind you this was 11 years ago, and it's weird to quote him as some sort of oracle. But it seems relevant.


They're usually used for an error clean-up section at the bottom.

Zed Shaw introduces some debug macros here which make use of a goto:


From that point on in the book, pretty much every function written has an "error:" label at the bottom where stuff gets cleaned up and memory freed. You can see his example code for it there.

Pretty useful macros, really. Context for the "goto considered harmful" always seems lost on young coders these days, unaware of the kind of spaghetti code that overuse of goto had caused.

Yeah, I've been on teams that have used this kind of error handling extensively, at several different companies. It's lightweight, very little is being done behind your back (do you know when your destructors are being called? really?) and it's easily inspected.

Also, never pass up the opportunity to troll a god-fearing "goto puritan" :-)

"Goto is bad" is something that professors tell first year computer science students because as computer scientists, the students will find novel ways of abusing them.

Using goto for error cleanup is pretty standard, easily readable, and understandable.

It avoids ugly braces and depth.

So, are gotos bad? It depends.

One of these days, "gotos: The Good Parts" will overshadow EWD's oft-abused essay, and the world will be spared highly nested, pointy-arrow C resource cleanup code.

Because they're not bad when you use them for actions which would go in a "finally" block in a language that supports exception handling.

I think what people are trying to say is that you shouldn't be taking too seriously all these advises about good and bad features in programming languages. Instead, try to understand the reasons behind such advises. All the bad things, that goto is blamed for, can be just as easily made with a bunch of methods in some object.

without a goto, you have to rely on functions/return values/pointers, which implies a function call (sometimes billions of times), which can have performance and design implications.

Because it is written in C. "Goto statements are bad" meant: lets start using languages that offer higher level constructs to replace the current usage of goto. Things like "loops" and "functions" and "exceptions". C did not get the memo.

> Because it is written in C.

Writing something in C does not automatically imply having to use goto.

> "Goto statements are bad"

Goto statements are not bad.

> Things like "loops" and "functions" and "exceptions". C did not get the memo.

C has loops and functions. Bro do you even K&R?

It might be a good idea to know what you're going to be talking about before opening your mouth.

>Writing something in C does not automatically imply having to use goto.

I didn't say it did. But any large enough C project will obviously use them.

>Goto statements are not bad.

Do you know what quotation marks are?

>C has loops and functions

It does not have exceptions. Which is what all the goto uses in question are being used for.

>It might be a good idea to know what you're going to be talking about before opening your mouth.

How ironic.

C has loops and functions. But you're right that modern use of goto is typically used in error handling to replace specific use cases of exceptions in a primitive way (If error, goto end of function where cleanup is done before the return statement.)

>C has loops and functions

Which leaves...

> But you're right that modern use of goto is typically used in error handling to replace specific use cases of exceptions in a primitive way

Exactly. I pointed out the context of "goto considered harmful". Obviously the one that applies to C is the one that is the reason for all the gotos in C code.

GOTO statements are not bad, they make your code run 10% faster while taking just 10 times as long to debug.

So if your code gets executed millions of times per second, like in some OS kernel, it may be wise to use GOTOs.

Otherwise, stay away.

Gotos are nowhere near as hard to debug as exceptions.

How's that? To debug GOTOs you have to place breakpoints on each possible detection of error (or at a shared trampoline). To debug exceptions, you just enable first-chance exception handling for the kind of exception you're interested in and you're done.

This is because Linux Kernel source code is not representative of what usual software should look like. And also because C is terrible ;)

Please get some experience writing kernel and driver code before making inane statements.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact