Question

The C Reference Manual, Appendix B describes two functions setjmp and longjmp for something called non-local jumps. Apart from the basic understanding that setjmp saves the state information and longjmp restores the state, I haven't been able to understand the exact flow and use cases for this feature.

So, what exactly does this feature accomplish and where is it useful?

Was it helpful?

Solution

As for the control flow: setjmp returns twice, and longjmp never returns. When you call setjmp for the first time, to store the environment, it returns zero, and the when you call longjmp, the control flow passes to return from setjmp with the value provided in the argument.

(Note that setjmp needn't actually be functions; it may well be a macro. longjmp is a function, though.)

Use cases are generally cited as "error handling", and "don't use these functions".

Here's a little control flow example:

jmp_buf env;

void foo()
{
    longjmp(&env, 10);                      +---->----+
}                                           |         |
                                            |         |
int main()              (entry)---+         ^         V
{                                 |         |         |
    if(setjmp(&env) == 0)         | (= 0)   |         | (= 10)
    {                             |         ^         |
        foo();                    +---->----+         |
    }                                                 +---->----+
    else                                                        |
    {                                                           |
        return 0;                                               +--- (end)
    }
}

Notes:

  • You cannot pass 0 to longjmp. If you do, 1 is returned by setjmp.

  • You must not return from the function that called setjmp before the corresponding longjmp. In other words, longjmp must only be called above setjmp in the call stack.

  • (Thanks to @wildplasser:) You cannot actually store the result of setjmp. If you want to return in several different ways, you can use a switch, though:

    switch (setjmp(&env))
    {
    case 0:   // first call
    case 2:   // returned from longjmp(&env, 2)
    case 5:   // returned from longjmp(&env, 5)
    // etc.
    }
    
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top