The use of goto and similar jumps in programming languages has been subject to intensive debate, starting from an article by Dijkstra [1968]. Still today you will find people that seriously object code as it is given here, but let us try to be pragmatic about
that: code with or without goto can be ugly and hard to follow.
I've seen this pattern frequently in the Linux source code. I think this is an example of a case where usage of goto improves readability and reduces errors.
The goto has gotten a bad rap over the years because of Dijkstra's paper. And that paper has unduly influenced a lot of incorrect thinking. There are valid use cases for goto, and this is certainly one of them.
I use it all the time like the example above. Particularly because it makes my life so much easier when developing and debugging embedded C code across various tool chains, some of which have less functionality than others.
Just curious, not a C developer by any means, but why wouldn't you use a function here instead of a goto? I'm confused how goto would reduce error/improve readability in that example.
Simply: a goto never returns while a function call returns to where it was called from.
So specifically in the example above, if you called failure-handling functions instead of using goto's then when the function returned you would continue execution on the next line after the function call. In the example above, that's clearly not what you want.
Now you could add some else's after the function calls to prevent execution from continuing. i.e. to get to the appropriate step in the free_* sequence at the bottom, but that starts to look messy. So I have to admit (not being a goto-lover), the above example reads very nicely.
It conforms to the "gotos might be okay if they only jump forward" rule of thumb I've heard.
I've also seen extensive use of gotos for exception handling in C. After the knee-jerk reaction ("...but but Dijkstra!") I came to appreciate it as a useful idiom.
To be fair, Dijkstra said "harmful", not "forbidden". He was also talking about encouraging structured procedural programming rather than a game of Who's Clever Enough to Follow the Spaghetti.
We do things that are harmful all the time, in limited appropriate situations. Cutting into your abdomen is harmful, but a skillfully used surgeon's scalpel can fix a bigger problem. That's not license to go roll around on a pile of jagged, rusty steel scrap. Missing sleep is harmful, but if you do it once in a while to keep your job or to escape a nighttime flash flood then it's helpful.
Dijkstra was intending to set the norm from which people should mindfully and occasionally deviate. The point wasn't to ban the use of labelled jumps entirely.
This looks fine to me. I wonder if C/C++ could be improved by introducing a new keyword `bail` which is the same as `goto` but is only allowed to jump to the bottom of the function. That way, codebases can outlaw `goto` but keep `bail`.
Yup, C++ has autocleanup. Of course if you are using fopen() instead something more modern you'll need to fclose(). Adding a new keywords to C is a long shot. Perhaps compilers could detect non-cleanup use of goto and give it a warning.
In a previous job where I wrote C code, I had a macro named "bail" that pretty much did that: log an error message, then jump to the cleanup section of the function.
Have you ever used goto in C? I feel like most people bash on C just because they heard Dijkstra said it, and that's it.
Most code I saw while teaching it were not good cases, but sometimes it's a very interesting technique that can make the code easier to understand and shorter. I think that use is beautiful.
I think you meant "bash on goto" instead of "bash on C"?
Regardless, yes, a ton of people do bash on it because of Dijkstra - but at the time, he had a good point. In the industry of the time (as I understand it - I was a kid when he wrote that), there was a lot of "cowboy coding" out there, with goto's "gone wild" - jumping into the middle of everywhere and everything - and producing "spaghetti code".
But as you note, it can be very useful and make things easier to read (for instance, jumping out of deeply nested if-then constructs - though I could also argue a refactor might be the better solution).
I was once part of a discussion in a forum about state machines, and one guy posted a very beautifully done state machine that used no select-case construct, but rather goto statements, but done in a tight way that mimic'ed a select-case construct. I was very impressed at the time; it was some code for PIC Basic IIRC.
In time, I've changed my views from seeing goto as "always bad", to "can be very useful, in some situations - provided you know the risks of the tool".
In other words - think very carefully before you rush into using it; maybe there's a better or cleaner way.
The only valid use of goto I've seen is for breaking out of nested loops; a goto statement is much easier than unwinding a bunch of breaks based on arbitrary logic or flags to notify each parent loop that a break is needed.
The main argument against goto comes from standard C++ side because there are so many edge cases where goto and longjmp will cause your exceptions and end-of-life semantics to go awry.
If I remember correctly, C++ flat out bans all uses of goto that could affect constructors and destructors. For example, something like this won't compile:
Now, longjmp is another matter. That thing is basically verboten in any sane C++ environment (and consequently, C libraries that use it across API boundary are very painful to use from C++; R hosting API is a great example of that).
It's been brought up that there are a few handy uses for goto. I think the reason it's so heavily preached against is because of its name. For someone just starting out, the word "goto" might sound like a handy tool that could be useful for all sorts of things.
But instead of a measured response to make it the last tool you reach for, it's been made into a pariah.
It's only more useful than structured code in a few niche situations, and even then, it doesn't usually provide massive benefits. It's a language construct that doesn't carry its weight.
The use of goto and similar jumps in programming languages has been subject to intensive debate, starting from an article by Dijkstra [1968]. Still today you will find people that seriously object code as it is given here, but let us try to be pragmatic about that: code with or without goto can be ugly and hard to follow.