...
The longjmp()
function should never be used to return control to a function that has terminated execution (see Undefined Behavior 120).
Signal masks, floating-point status flags, and the state of open files are not saved by the setjmp()
function. If signal masks need to be saved, the sigsetjmp()
function should be used.
This recommendation is related to SIG32-C. Do not call longjmp() from inside a signal handler and ENV32-C. All atexit handlers must return normally.
Implementation Details
glibc v2.11.1 defines the jmp_buf
type as follows:
Platform | | Registers Saved |
---|---|---|
i386 | 24 | |
x86_64 | 64 | |
No other state information is saved.
Noncompliant Code Example
...
Code Block | ||
---|---|---|
| ||
jmp_buf buf; void f(void) { g(); h(); return; } void g(void) { volatile int i = 10; if (setjmp(buf) !== 0) { printf("i = %d\n", i); } else { /* printf("longjmp was invoked*/: i = %d\n", i); exit(0); } return; } void h(void) { char b[16]; /* ... */memset(b, 0, 16); longjmp(buf, 1); } |
Implementation Details
When compiled for i386 using GCC v4.1.2, the above example outputs the following when run:
Code Block |
---|
i = 10 i = 0 |
Because g()
has finished executing at the time longjmp()
is called, it is no longer on the stack. When h()
is invoked, its stackframe overwrites the stackframe of g()
. In this case i
was located in the same location as the end of array b
. The call to memset()
sets the four bytes that i
occupied in g()
to 0, so when longjmp()
sends control back to function g()
, it prints out a value of 0.
Compliant Solution
The longjmp()
function should only be used when the function containing the corresponding setjmp()
is guaranteed not to have terminated completed execution, as in the following example.
Code Block | ||
---|---|---|
| ||
jmp_buf buf; void f(void) { volatile int i = 10; if (setjmp(buf) !== 0) { /* longjmp was invoked */printf("i = %d\n", i); } else { printf("longjmp: i = %d\n", i); hexit(0); } h(); return; } void h(void) { char b[16]; /* ... */memset(b, 0, 16); longjmp(buf, 1); } |
Implementation Details
In this example there is no risk of overwriting i
because the stackframe of f()
is still on the stack, so when h
is invoked, the two stackframes will not overlap.
Noncompliant Code Example
...