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;
}
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)
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.