<setjmp.h> — 非局部跳转

头文件: #include <setjmp.h>
提供 C 语言的非局部跳转机制——类似于其他语言中的异常处理,但更底层。允许从深层嵌套函数直接跳回早期执行点。


核心类型与函数

类型/函数签名说明
jmp_bufjmp_buf env;数组类型,保存调用者的执行环境(寄存器、栈指针、程序计数器)
setjmpint setjmp(jmp_buf env)保存当前环境到 env;首次返回 0,longjmp 跳回时返回非零
longjmpvoid longjmp(jmp_buf env, int val)恢复 env 中保存的环境,使 setjmp 返回 val(必须非零)

基本用法

#include <setjmp.h>
jmp_buf env;
 
void inner(void) {
    printf("error detected, jumping back\n");
    longjmp(env, 1);
}
 
int main(void) {
    if (setjmp(env) == 0) {
        printf("first call\n");
        inner();
    } else {
        printf("jumped back from longjmp\n");
    }
    return 0;
}

重要约束与陷阱

1. volatile 变量

setjmplongjmp 之间修改的自动变量(非 volatile)在 longjmp 后的值未定义。必须用 volatile 修饰。

2. 函数返回限制

包含 setjmp 调用的函数返回后,其 jmp_buf 变为无效。

3. 资源泄漏

longjmp 不展开栈,不调用 freefclose 或释放互斥锁。跳转前必须手动清理资源:

/* 危险:FILE* 可能泄漏 */
FILE *fp = fopen("data.txt", "r");
if (error) longjmp(env, 1);   // fp 未关闭!
fclose(fp);

典型应用

场景说明
深层嵌套中的错误恢复从多层调用链中直接跳出
协程/纤程实现保存和恢复执行上下文
信号处理中的恢复配合 volatile sig_atomic_t
解释器/虚拟机的异常简单的 try-catch 机制

setjmp/longjmp vs C++ 异常

特性setjmp/longjmpC++ try/catch
栈展开
析构函数调用是(RAII)
类型安全否(val 为 int)

跨语言参考