When goto Might Be Necessary

In last week’s Lesson, I covered the goto keyword the way most instructors do: I explained that it’s not needed and admonished you not to use it lest you be labeled an complete and utter dork. Still, why would such a superfluous method of program control be included if it’s awkward and unnecessary?

In their seminal tome, The C Programming Language, Kernighan and Ritchie write about the goto statement. I included the first part of the quote in last week’s Lesson. The rest of it is:

…we will suggest a few situations where goto‘s [sic] may find a place. the most common use is to abandon processing in some deeply nested structure, such as breaking out of two loops at once.

K&R then proceed to demonstrate a code snippet where goto breaks out of a nested for loop, but then they immediately show a more readable example that does the same thing without using goto. Again, they prove that goto is never necessary.

Yet, the example was too innocent. In fact, goto would theoretically be necessary in a large program to provide an exit from one or more routines that otherwise have no easy way out.

Consider code where you have multiple modules and functions, several of which can error but at the point of the error you may not know exactly how to unwind loops and return from functions to access the error-management routines. I’ve encountered this situation in my coding several times, primarily for large, multi-module and multitasking programs. Even then, I’ve never used goto.

Instead of goto, the solution I employ are two functions designed specifically to deal with program recovery: setjmp() and longjmp(). I find it interesting that both functions use the assembly language jmp for “jump,” which is what goto effectively is.

The setjmp() function saves the program’s environment, with such details as the stack, variable values, and other program conditions. It serves as an anchor, a re-entry point into your code from another location.

The longjmp() function bails out of a location deeper in your code. It’s called after the setjmp() function and it returns execution to the spot in the code where setjmp() was called. Further, it returns a value to setjmp() so your code can evaluate what happened, and so that setjmp() knows whether it’s being initialized or handling a return.

Both functions require the setjmp.h header file. They both use a variable of the jmp_buf type to retain the program environment.

Yes, these functions work like a goto, but they’re far more logical and useful to help you out of tight situations.

I can’t show my code here as an example because it’s thousands of lines long. Basically, I wrote a communications program that spawned multiple processes to monitor incoming data. Upon a disconnect, the longjmp() function bailed out of whichever routine detected the dropped signal and the setjmp() function reset the program. That way I didn’t have to figure out which routine called the processes, break out of unknown loops, or reset variables: setjmp() and longjmp() did the work for me.

Bottom line: K&R are correct. The goto statement is never necessary. No matter which way you try to paint your code into a corner, you can always flee without needing a goto.

Leave a Reply