my-server
← Wiki Redirected from Longjmp

Setjmp.h

is a header defined in the C standard library to provide "non-local jumps": control flow that deviates from the usual subroutine call and return sequence. The complementary functions <code>setjmp</code> and <code>longjmp</code> provide this functionality.

A typical use of <code>setjmp</code>/<code>longjmp</code> is implementation of an exception mechanism that exploits the ability of <code>longjmp</code> to reestablish program or thread state, even across multiple levels of function calls. A less common use of <code>setjmp</code> is to create syntax similar to coroutines.

Member functions

: Sets up the local <code>jmp_buf</code> buffer and initializes it for the jump. This routine saves the program's calling environment in the environment buffer specified by the <code>env</code> argument for later use by <code>longjmp</code>. If the return is from a direct invocation, <code>setjmp</code> returns 0. If the return is from a call to <code>longjmp</code>, <code>setjmp</code> returns a nonzero value.
: Restores the context of the environment buffer <code>env</code> that was saved by invocation of the <code>setjmp</code> routine in the same invocation of the program. Invoking <code>longjmp</code> from a nested signal handler is undefined. The value specified by <code>value</code> is passed from <code>longjmp</code> to <code>setjmp</code>. After <code>longjmp</code> is completed, program execution continues as if the corresponding invocation of <code>setjmp</code> had just returned. If the <code>value</code> passed to <code>longjmp</code> is 0, <code>setjmp</code> will behave as if it had returned 1; otherwise, it will behave as if it had returned <code>value</code>.

<code>setjmp</code> saves the current environment (the program state), at some point of program execution, into a platform-specific data structure (<code>jmp_buf</code>) that can be used at some later point of program execution by <code>longjmp</code> to restore the program state to that saved by <code>setjmp</code> into <code>jmp_buf</code>. This process can be imagined to be a "jump" back to the point of program execution where <code>setjmp</code> saved the environment. The (apparent) return value from <code>setjmp</code> indicates whether control reached that point normally (zero) or from a call to <code>longjmp</code> (nonzero). This leads to a common idiom: .

POSIX.1 does not specify whether <code>setjmp</code> and <code>longjmp</code> save and restore the current set of blocked signals; if a program employs signal handling it should use POSIX's <code>sigsetjmp</code>/<code>siglongjmp</code>.

Member types

<code>jmp_buf</code> : An array type suitable for holding the information needed to restore a calling environment.

The C99 Rationale describes <code>jmp_buf</code> as being an array type for backward compatibility; existing code refers to <code>jmp_buf</code> storage locations by name (without the <code>&</code> address-of operator), which is only possible for array types. It notes that it can simply be a one-member-long array with its single member being the actual data; indeed, this is the approach employed by the GNU C library, which defines the type as <code>struct __jmp_buf_tag[1]</code>.

Caveats and limitations

When a "non-local goto" is executed via <code>setjmp</code>/<code>longjmp</code> in C++, normal "stack unwinding" does not occur. Therefore, any required cleanup actions will not occur either. This could include closing file descriptors, flushing buffers, or freeing heap-allocated memory.

If the function in which <code>setjmp</code> was called returns, it is no longer possible to safely use <code>longjmp</code> with the corresponding <code>jmp_buf</code> object. This is because the stack frame is invalidated when the function returns. Calling <code>longjmp</code> restores the stack pointer, which—because the function returned—would point to a non-existent and potentially overwritten or corrupted stack frame.

Similarly, C99 does not require that <code>longjmp</code> preserve the current stack frame. This means that jumping into a function which was exited via a call to <code>longjmp</code> is undefined.

Example usage

Simple example

The example below shows the basic idea of setjmp. There, <code>main()</code> calls <code>first()</code>, which in turn calls <code>second()</code>. Then, <code>second()</code> jumps back into <code>main()</code>, skipping <code>first()</code>'s call of <code>printf()</code>.

When executed, the above program will output:

Notice that although the <code>first()</code> subroutine gets called, "<code>first</code>" is never printed, as <code>second()</code> never returns control to <code>first()</code>. Instead, "<code>main</code>" is printed when the conditional statement <code>if (!setjmp(buf))</code> is checked a second time.

Exception handling

In this example, <code>setjmp</code> is used to bracket exception handling, like <code>try</code> in some other languages. The call to <code>longjmp</code> is analogous to a <code>throw</code> statement, allowing an exception to return an error status directly to the <code>setjmp</code>. The following code adheres to the 1999 ISO C standard and Single UNIX Specification by invoking <code>setjmp</code> in a limited range of contexts:

  • As the condition to an <code>if</code>, <code>switch</code> or iteration statement
  • As above in conjunction with a single <code>!</code> 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 <code>setjmp</code> 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".

This program's output is:

Cooperative multitasking

C99 provides that <code>longjmp</code> 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 <code>return</code> or <code>longjmp</code> is undefined. However, most implementations of <code>longjmp</code> 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 <code>setjmp</code>. In many environments (such as Really Simple Threads and TinyTimbers), idioms such as can allow a called function to effectively pause-and-resume at a <code>setjmp</code>.

This is exploited by thread libraries to provide cooperative multitasking facilities without using <code>setcontext</code> or other fiber facilities.

Considering that <code>setjmp</code> to a child function will generally work unless sabotaged, and <code>setcontext</code>, as part of POSIX, is not required to be provided by C implementations, this mechanism may be portable where the <code>setcontext</code> 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 <code>main()</code> 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.

References

Further reading

External links