Namespaces
Variants

longjmp

From cppreference.net
定义于头文件 <setjmp.h>
void longjmp ( jmp_buf env, int status ) ;
(C11前)
_Noreturn void longjmp ( jmp_buf env, int status ) ;
(C11起)
(C23前)
[ [ noreturn ] ] void longjmp ( jmp_buf env, int status ) ;
(C23起)

加载由先前调用 setjmp 所保存的执行上下文 env 。此函数不会返回。控制权将转移至设置 env 的宏 setjmp 的调用点。随后该 setjmp 将返回作为 status 传递的值。

如果调用 setjmp 的函数已退出(无论是通过返回还是通过栈中更高层级的 longjmp 退出),则行为未定义。换言之,仅允许沿调用栈向上进行长跳转。

跨线程跳转(若调用 setjmp 的函数由其他线程执行)亦属未定义行为。

(since C11)

若在调用 setjmp 时,存在作用域内的 VLA 或其他 可变修改类型 变量,且控制流离开了该作用域,则对该 setjmp longjmp 会引发未定义行为,即使控制流仍保留在函数内部。

在栈回退过程中, longjmp 不会释放任何 VLA,若其生命周期以此方式终止可能导致内存泄漏:

void g(int n)
{
    int a[n]; // a 可能保持已分配状态
    h(n); // 不会返回
}
void h(int n)
{
    int b[n]; // b 可能保持已分配状态
    longjmp(buf, 2); // 可能导致 h 的 b 和 g 的 a 内存泄漏
}
(C99 起)

目录

参数

env - 指向由 setjmp 保存的程序执行状态的变量
status - setjmp 返回的值。若等于 0 ,则改用 1

返回值

(无)

注释

longjmp 旨在处理无法正常返回的意外错误情况,这与其他编程语言中的异常处理机制类似。

示例

#include <stdio.h>
#include <setjmp.h>
#include <stdnoreturn.h>
jmp_buf my_jump_buffer;
noreturn void foo(int status) 
{
    printf("foo(%d) called\n", status);
    longjmp(my_jump_buffer, status + 1); // will return status+1 out of setjmp
}
int main(void)
{
    volatile int count = 0; // modified local vars in setjmp scope must be volatile
    if (setjmp(my_jump_buffer) != 5) // compare against constant in an if
        foo(++count);
}

输出:

foo(1) called
foo(2) called
foo(3) called
foo(4) called

参考文献

  • C17 标准 (ISO/IEC 9899:2018):
  • 7.13.2.1 longjmp 宏 (p: 191-192)
  • C11 标准 (ISO/IEC 9899:2011):
  • 7.13.2.1 longjmp 宏 (p: 263-264)
  • C99标准(ISO/IEC 9899:1999):
  • 7.13.2.1 longjmp宏(页码:244-245)
  • C89/C90 标准 (ISO/IEC 9899:1990):
  • 4.6.2.1 longjmp 函数

参见

保存执行上下文
(函数宏)
C++ 文档 for longjmp