setjmp
and longjmp
provide this functionality.
A typical use of setjmp
/longjmp
is implementation of an exception mechanism that exploits the ability of longjmp
to reestablish program or thread state, even across multiple levels of function calls. A less common use of setjmp
is to create syntax similar to Member functions
;jmp_buf
buffer and initializes it for the jump. This routineISO C states that setjmp
must be implemented as a macro, but POSIX explicitly states that it is undefined whether setjmp
is a macro or a function. 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.
; env
that was saved by invocation of the setjmp
routine in the same invocation of the program. Invoking longjmp
from a nested signal handler is 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 environment (the program state), at some point of program execution, into a platform-specific data structure (jmp_buf
) that can be used at some later point of program execution by longjmp
to restore the program state to that saved by setjmp
into jmp_buf
. This process can be imagined to be a "jump" back to the point of program execution where setjmp
saved the environment. The (apparent) setjmp
indicates whether control reached that point normally (zero) or from a call to longjmp
(nonzero). This leads to a common setjmp
and longjmp
save and restore the current set of blocked sigsetjmp
/siglongjmp
.
Member types
;jmp_buf
: An array type suitable for holding the information needed to restore a calling environment.
The C99 Rationale describes jmp_buf
as being an array type for jmp_buf
storage locations by name (without the &
address-of operator), which is only possible for array types.C99 Rationale, version 5.10, April 2003struct __jmp_buf_tag /code>.
Caveats and limitations
When a "non-local goto" is executed via setjmp
/longjmp
in C++, normal "stack unwinding
In computer science, a call stack is a stack data structure that stores information about the active subroutines and inline blocks of a computer program. This type of stack is also known as an execution stack, program stack, control stack, run- ...
" does not occur. Therefore, any required cleanup actions will not occur either. This could include closing file descriptor
In Unix and Unix-like computer operating systems, a file descriptor (FD, less frequently fildes) is a process-unique identifier (handle) for a file or other input/output resource, such as a pipe or network socket.
File descriptors typically h ...
s, flushing buffers, or freeing heap-allocated memory.
If the function in which setjmp
was called returns, it is no longer possible to safely use longjmp
with the corresponding jmp_buf
object. This is because the stack frame
In computer science, a call stack is a stack data structure that stores information about the active subroutines and inline blocks of a computer program. This type of stack is also known as an execution stack, program stack, control stack, run- ...
is invalidated when the function returns. Calling longjmp
restores the stack pointer, which—because the function returned—would point to a non-existent and potentially overwritten or corrupted stack frame.setjmp(3)
Similarly, C99 does not require that longjmp
preserve the current stack frame. This means that jumping into a function which was exited via a call to longjmp
is undefined.ISO/IEC 9899:1999
2005, 7.13.2.1:2 and footnote 211
Example usage
Simple example
The example below shows the basic idea of setjmp. There, main()
calls first()
, which in turn calls second()
. Then, second()
jumps back into main()
, skipping first()
's call of printf()
.
#include
#include
static jmp_buf buf;
void second()
void first()
int main()
When executed, the above program will output:
second
main
Notice that although the first()
subroutine gets called, "first
" is never printed, as second()
never returns control to first()
. Instead, "main
" is printed when the conditional statement if (!setjmp(buf))
is checked a second time.
Exception handling
In this example, setjmp
is used to bracket exception handling, like try
in some other languages. The call to longjmp
is analogous to a throw
statement, allowing an exception to return an error status directly to the setjmp
. The following code adheres to the 1999 ISO C standard and Single UNIX Specification
The Single UNIX Specification (SUS) is a standard for computer operating systems, compliance with which is required to qualify for using the "UNIX" trademark. The standard specifies programming interfaces for the C language, a command-line shell, ...
by invoking setjmp
in a limited range of contexts:
* As the condition to an if
, switch
or iteration statement
* As above in conjunction with a single !
or comparison with an integer constant
* As a statement (with the return value unused)
Following these rules can make it easier for the implementation to create the environment buffer, which can be a sensitive operation. More general use of setjmp
can cause undefined behaviour, such as corruption of local variables; conforming compilers and environments are not required to protect or even warn against such usage. However, slightly more sophisticated idioms such as are common in literature and practice, and remain relatively portable. A simple conforming methodology is presented below, where an additional variable is maintained along with the state buffer. This variable could be elaborated into a structure incorporating the buffer itself.
In a more modern-looking example, the usual "try" block would be implemented as a setjmp (with some preparation code for multilevel jumps, as seen in ), the "throw" as longjmp with the optional parameter as the exception, and the "catch" as the "else" block under "try".
#include
#include
#include
#include
static void first();
static void second();
/* Use a file scoped static variable for the exception stack so we can access
* it anywhere within this translation unit. */
static jmp_buf exception_env;
static int exception_type;
int main(void)
static void first()
static void second()
This program's output is:
calling first
entering first
calling second
entering second
second failed, exception type: 3; remapping to type 1
first failed, exception type: 1
Cooperative multitasking
C99 provides that longjmp
is guaranteed to work only when the destination is a calling function, i.e., that the destination scope is guaranteed to be intact. Jumping to a function that has already terminated by return
or longjmp
is undefined. However, most implementations of longjmp
do not specifically destroy local variables when performing the jump. Since the context survives until its local variables are erased, it could actually be restored by setjmp
. In many environments (such a
Really Simple Threads
an
TinyTimbers
, idioms such as can allow a called function to effectively pause-and-resume at a setjmp
.
This is exploited by thread libraries to provide cooperative multitasking
Cooperative multitasking, also known as non-preemptive multitasking, is a computer multitasking technique in which the operating system never initiates a context switch from a running Process (computing), process to another process. Instead, in o ...
facilities without using setcontext
setcontext is one of a family of C library functions (the others being getcontext, makecontext and swapcontext) used for context control. The setcontext family allows the implementation in C of advanced control flow patterns such as iterators, fi ...
or other fiber
Fiber (spelled fibre in British English; from ) is a natural or artificial substance that is significantly longer than it is wide. Fibers are often used in the manufacture of other materials. The strongest engineering materials often inco ...
facilities.
Considering that setjmp
to a child function will generally work unless sabotaged, and setcontext
, as part of POSIX, is not required to be provided by C implementations, this mechanism may be portable where the setcontext
alternative fails.
Since no exception will be generated upon overflow of one of the multiple stacks in such a mechanism, it is essential to overestimate the space required for each context, including the one containing main()
and including space for any signal handlers that might interrupt regular execution. Exceeding the allocated space will corrupt the other contexts, usually with the outermost functions first. Unfortunately, systems requiring this kind of programming strategy are often also small ones with limited resources.
#include
#include
jmp_buf mainTask, childTask;
void call_with_cushion();
void child();
int main() " after first time that child yields
while (1)
}
void call_with_cushion()
void child()
References
Further reading
*
External links
* {{man, sh, setjmp, SUS, set jump point for a non-local goto
is there sigsetjmp/siglongjmp (again)
(about this functions in mingw
MinGW ("Minimalist GNU for Windows"), formerly mingw32, is a free and open source software development environment to create Microsoft Windows applications.
MinGW includes a port of the GNU Compiler Collection (GCC), GNU Binutils for Windows ...
/MSYS
MinGW ("Minimalist GNU for Windows"), formerly mingw32, is a free and open source software development environment to create Microsoft Windows applications.
MinGW includes a port of the GNU Compiler Collection (GCC), GNU Binutils for Windows ...
)
Articles with example C code
C standard library headers
Control flow