Is it allowed to do longjmp() multiple times for one setjmp() call?

1.3k views Asked by At

In my understanding, a typical usage of setjmp() and longjmp() is exception handling (usage in libpng should be a famous example of that) and there will be at most one call of longjmp() for one setjmp() call.

Is it safely allowed to do longjmp() multiple times for one setjmp() call like this?

#include <stdio.h>
#include <setjmp.h>

jmp_buf jb;
int i;

int main(void) {
    i = 0;
    setjmp(jb);
    printf("%d\n", i);
    i++;
    if (i < 10) longjmp(jb, 1);
    return 0;
}

Output:

0
1
2
3
4
5
6
7
8
9

I successfully got the expected output from this execution, but is this guaranteed? Or will jmp_buf invalidated when longjmp() is once used for that?

setcontext - Wikipedia says "They may be viewed as an advanced version of setjmp/longjmp; whereas the latter allows only a single non-local jump up the stack", but I didn't find descriptions that disallow multiple usage of longjmp() like this from N1570 7.13 Nonlocal jumps <setjmp.h>.

I know that using setjmp() and longjmp() is discouraged, but I am wondering if they can be used as a workaround when using loop statements (for, while, do-while) and goto statements is banned but using setjmp() and longjmp() is not banned in some programming quiz. (using recursion may be answers for this type of quiz, but it has risk of stack overflow when trying to deal with large data that require many iterations)

1

There are 1 answers

6
John Bollinger On BEST ANSWER

Is it safely allowed to do longjmp() multiple times for one setjmp() call like this?

It is possible to construct a strictly conforming program that calls longjmp() multiple times to return to the point of the same setjmp() call. It comes down to the state of the abstract machine, including memory contents, and especially the state of the jmp_buf in which a setjmp() call records the state required to return to the point of that call. The standard specifies that

All accessible objects have values, and all other components of the abstract machine have state, as of the time the longjmp function was called, except that [... details that can be avoided or made immaterial ...].

(C2018 7.13.2.1/3)

In particular, that means that the longjmp() call must not change the value of the jmp_buf from which it gets its information, and there cannot be any hidden state elsewhere that longjmp() could update to mark the corresponding setjmp() as being used up. If machine state permits a conforming longjmp() call, then an equivalent longjmp() call must still be conforming after the resulting second (or third, etc.) return from the corresponding setjmp() call.