The setjmp()
macro should only be invoked from only one of the contexts listed in §7.13.1.1 of [ISO/IEC 9899:19992011]. Invoking setjmp()
outside of one of these contexts results in undefined behavior. (See Undefined Behavior 119 undefined behavior 125.)
After invoking longjmp()
, nonnon–volatile-volatile-qualified local objects should not be accessed if their values could have changed since the invocation of setjmp()
. Their value in this case is considered indeterminate, and accessing them is undefined behavior. (See Undefined Behavior 121 undefined behavior 127, 10.)
The longjmp()
function should never be used to return control to a function that has terminated execution. (See Undefined Behavior 120126.)
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 rules SIG32-C. Do not call longjmp() from inside a signal handler and ENV32-C. All atexit handlers must return normally.
...
Code Block | ||||
---|---|---|---|---|
| ||||
jmp_buf buf;
void f(void) {
int i = setjmp(buf);
if (i == 0) {
g();
} else {
/* longjmp was invoked */
}
}
void g(void) {
/* ... */
longjmp(buf, 1);
}
|
...
Code Block | ||||
---|---|---|---|---|
| ||||
jmp_buf buf;
void f(void) {
if (setjmp(buf) == 0) {
g();
} else {
/* longjmp was invoked */
}
}
void g(void) {
/* ... */
longjmp(buf, 1);
}
|
...
Code Block | ||||
---|---|---|---|---|
| ||||
jmp_buf buf;
unsigned char b[] = {0xe5, 0x06, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00};
int main(void) {
setup();
do_stuff();
return 0;
}
void setup(void) {
f();
}
void f(void) {
g();
}
void g(void) {
if (setjmp(buf) == 0) {
printf("setjmp() invoked\n");
} else {
printf("longjmp() invoked\n");
}
}
void do_stuff(void) {
char a[8];
memcpy(a, b, 8);
/* ... stuff ... */
longjmp(buf, 1);
}
void bad(void) {
printf("Should not be called!\n");
exit(1);
}
|
...
When compiled for x86-64 using GCC v4.1.2 on Linux, the above example outputs the following when run:
Code Block |
---|
setjmp() invoked
longjmp() invoked
Should not be called!
|
...
Code Block | ||||
---|---|---|---|---|
| ||||
jmp_buf buf;
unsigned char b[] = {0xe5, 0x06, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00};
int main(void) {
if (setjmp(buf) == 0) {
printf("setjmp() invoked\n");
} else {
printf("longjmp() invoked\n");
}
do_stuff();
return 0;
}
void do_stuff(void) {
char a[8];
memcpy(a, b, 8);
/* ... stuff ... */
longjmp(buf, 1);
}
void bad(void) {
printf("Should not be called!\n");
exit(1);
}
|
...
Code Block | ||||
---|---|---|---|---|
| ||||
jmp_buf buf;
void f(void) {
int i = 0;
if (setjmp(buf) != 0) {
printf("%i\n", i);
/* ... */
}
i = 2;
g();
}
void g(void) {
/* ... */
longjmp(buf, 1);
}
|
...
Code Block | ||||
---|---|---|---|---|
| ||||
jmp_buf buf;
void f(void) {
volatile int i = 0;
if (setjmp(buf) != 0) {
printf("%i\n", i);
/* ... */
}
i = 2;
g();
}
void g(void) {
/* ... */
longjmp(buf, 1);
}
|
...