setjmp and longjmp are C library functions that implement a form of non-local control transfer - essentially allowing you to jump from deep within a call stack back to an earlier point, bypassing normal function return mechanisms.
What they are
setjmp(jmp_buf env) - Saves the current execution context (registers, stack pointer, program counter) into a jmp_buf structure and returns 0 initially.
longjmp(jmp_buf env, int val) - Restores the execution context saved in env, causing execution to resume at the setjmp call, but this time setjmp returns val (or 1 if val is 0).
The jmp_buf is an opaque data type that stores the machine state - typically registers and stack information needed to restore execution.
Why they're used
Error handling before exceptions - Provides a way to bail out of deeply nested function calls when an error occurs, similar to exceptions in higher-level languages.
Early returns from complex call chains - When you need to abort processing and return to a known safe point.
Implementing coroutines/cooperative multitasking - Though this is quite advanced and error-prone.
Signal handling - Sometimes used in signal handlers to return to a safe execution point.
How they work
#include <setjmp.h>
#include <stdio.h>
jmp_buf error_buf;
void deep_function() {
printf("About to jump back\n");
longjmp(error_buf, 42); // Jump back with value 42
printf("This never executes\n");
}
void middle_function() {
deep_function();
printf("This also never executes\n");
}
int main() {
int result = setjmp(error_buf);
if (result == 0) {
printf("First time through setjmp\n");
middle_function();
} else {
printf("Jumped back with value: %d\n", result);
}
return 0;
}
Important caveats
Undefined behavior with local variables - Local variables in the function containing
setjmpmay have indeterminate values afterlongjmpunless they'revolatile.Stack unwinding issues - Unlike exceptions,
longjmpdoesn't call destructors or cleanup code in intermediate functions.Jumping constraints - You can only
longjmpto asetjmpthat's still active on the stack. Jumping to an expired stack frame is undefined behavior.Signal safety -
longjmpfrom a signal handler has restrictions and portability issues.
Why they're generally avoided
Modern C programming typically avoids setjmp/longjmp because:
- They make code harder to reason about
- They bypass normal cleanup mechanisms
- Error codes or structured error handling are usually clearer
- They can interact poorly with modern compiler optimizations
- They're not thread-safe without careful consideration
They're still occasionally useful for implementing interpreters, parsers with error recovery, or in systems programming where you need emergency bailout mechanisms, but they should be used sparingly and with great care.