In the case that a local jmp_buf
is actually represented by registers rather than stack memory, is it possible for setjmp
or longjmp
to cause the contents of the local jmp_buf
to be indeterminate when setjmp
returns from a longjmp
?
The suggested duplicate Is it allowed to do longjmp() multiple times for one setjmp() call? asks in the context of a global variable. It was suggested since the answer explains that the variable is not modified in a way that would prevent it from being subsequently called, that sufficiently answers the question for a local variable too.
However, treatment of a local variable differs from a global variable. In particular, if the local jmp_buf
variable is actually held in registers and not memory, restoration after longjmp
may not render a reusable jmp_buf
variable.
As an academic exercise, I was attempting to use setjmp
as a substitute for goto
. To keep the loop replacement local to the function, the jmp_buf
used is also a local variable.
void foo (int n) {
jmp_buf jb;
volatile int i;
i = setjmp(jb);
if (i < n) {
do_stuff(i);
longjmp(jb, ++i);
}
}
I understand that non-volatile local variables that have been modified between the setjmp
call and the longjmp
call are unspecified after longjmp
. However, I was curious about the local jmp_buf
variable itself, particularly in the case where the jmp_buf
variable is represented by registers rather than memory on the stack.
It is unclear if longjmp
itself can be considered something that may modify the local jmp_buf
variable, and whether this means its contents are unspecified when setjmp
returns after the call to longjmp
.
I thought I could easily dispatch the issue by declaring jb
to be volatile
, but this triggered a warning (which I treat as an error):
... error: passing argument 1 of ‘_setjmp’ discards ‘volatile’ qualifier from pointer target type [-Werror=discarded-qualifiers]
setjmp(jb);
^~
Also, the specification of setjmp
does not speak to whether it is saving the register values as they would be after setting the jmp_buf
or before setting the jmp_buf
.
If I need to be concerned about it, I can create a volatile copy of the jmp_buf
and copy its contents around. But, I'd like to avoid that if it isn't required.