Setjmp.h
From Wikipedia, the free encyclopedia
C++ Standard Library headers |
C Standard Library headers |
---|
assert.h |
ctype.h |
errno.h |
float.h |
limits.h |
locale.h |
math.h |
setjmp.h |
signal.h |
stdarg.h |
stddef.h |
stdio.h |
string.h |
stdlib.h |
time.h |
- The correct title of this article is setjmp.h. The initial letter is shown capitalized due to technical restrictions.
setjmp.h is a header defined in the C standard library to provide "non-local jumps" (control flow) outside of the normal function call and return sequence, typically to implement a crude form of exception handling. The paired functions setjmp and longjmp provide this functionality through first saving the environment with setjmp
from which longjmp
can "jump" to.
The typical use for setjmp/longjmp
is for exception handling - by calling longjmp
, the program can jump out of many levels of nested function calls without having to go to the trouble of setting flag variables which need to be checked in each function. A problem with the use of setjmp/longjmp
is that cleanup (closing file descriptors, flushing buffers, freeing heap-allocated memory, etc.) will not be conducted.
Neither setjmp
nor longjmp
save or restore the current set of blocked signals - if a program employs signal handling it should use sigsetjmp/siglongjmp
.
Compared to mechanisms in higher-level programming languages such as Java, C++, C#, and particularly in older high-level languages such as Algol 60 and Common Lisp, the setjmp
/longjmp
technique is archaic. These languages provide far more powerful exception handling techniques.
Contents |
[edit] Member functions
int setjmp(jmp_buf env) |
Sets up the local jmp_buf buffer and initializes it for the jump. This macro saves the program's calling environment in the environment buffer specified by the env argument for later use by longjmp . If the return is from a direct invocation, setjmp returns 0. If the return is from a call to longjmp , setjmp returns a nonzero value. |
void longjmp(jmp_buf env, int value) |
Restores the context of the environment buffer env that was saved by invocation of the setjmp macro in the same invocation of the program. Invoking longjmp from a nested signal handler is undefined. The value specified by value is passed from longjmp to setjmp . After longjmp is completed, program execution continues as if the corresponding invocation of setjmp had just returned. If the value passed to longjmp is 0, setjmp will behave as if it had returned 1; otherwise, it will behave as if it had returned value . |
setjmp
saves the current execution state into a structure of type jmp_buf
; later, a longjmp
call can transfer control to the point immediately after the call to setjmp
. The (apparent) return value from setjmp
indicates whether control reached that point normally or from a call to longjmp
; this allows the use of a common idiom, placing the setjmp
in the condition of an if/else block, similar to that with the fork
system call.
[edit] Member types
jmp_buf |
An array type suitable for holding the information needed to restore a calling environment. |
[edit] Example
This is an example of setjmp
usage, in which switch (setjmp(buf))
operates similarly to a try-catch block in some other languages. The call to longjmp
is analogous to a throw
statement, allowing an exception status to be returned directly from arbitrary levels of nested function calls. Notice that unlike some other languages, there is no provision for finally
blocks.
Also, notice that setjmp
is invoked by itself inside the controlling expression of the switch
statement; this is one of a very few ways setjmp
is allowed to be invoked in a conforming C program. The reason for this restriction is to limit the need to save and restore the values of temporary registers or stack locations around the setjmp
call.[1]
#include <stdio.h> #include <setjmp.h> void first(void); void second(void); /* Global "environment" variable; this must be in scope if longjmp is to be called. */ static jmp_buf buf; int main (int argc, char **argv) { int specific_status = 0; switch (setjmp(buf)) { case 0: { /* Run code that may signal failure via longjmp. */ printf("calling first\n"); first(); printf("first succeeded\n"); /* not reached */ break; } case 3: specific_status = 3; /* fallthrough */ default: { /* Take any action required on failure. */ if (specific_status != 0) printf("first failed, status %d\n", specific_status); else printf("first failed, status nonzero\n"); break; } } return 0; } void first(void) { printf("calling second\n"); /* If second calls longjmp, this code has no way of knowing, so it can't perform any cleanup. */ second(); printf("second succeeded\n"); /* not reached */ } void second(void) { /* Normally the code here would try to do something useful and longjmp on failure, but here we're just demonstrating longjmp's ability to return from nested function calls. Note that this is not as general as a throw in other languages since it needs to be aware of the jmp_buf to be used to jump back to a specific caller. Alternatively the jmp_buf could be in main scope and passed in the function parameters, making error handling more general but complicating function calls. */ longjmp(buf, 3); }
[edit] References
- ^ C99 Rationale, version 5.10, April 2003:
- Unfortunately, any implementation of setjmp as a conventional called function cannot know enough about the calling environment to save any temporary registers or dynamic stack locations used part way through an expression evaluation. ... The temporaries may be correct on the initial call to setjmp, but are not likely to be on any return initiated by a corresponding call to longjmp. These considerations dictated the constraint that setjmp be called only from within fairly simple expressions, ones not likely to need temporary storage.[1]