Namespaces
Variants

longjmp

来自 zh.cppreference.net
< c | 程序
定义于头文件 <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 起)

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

如果调用 setjmp 的函数已经退出(无论是通过返回还是通过不同的 longjmp 更高的调用栈),行为未定义。换句话说,只允许向调用栈上层进行非局部跳转。

跨线程跳转(如果调用 setjmp 的函数由另一个线程执行)也是未定义行为。

(自 C11 起)

如果当 setjmp 被调用时,一个 VLA 或另一个 可变修改类型 变量在作用域内并且控制离开该作用域,longjmp 对该 setjmp 调用会引发未定义行为,即使控制权仍留在函数内。

在向调用栈上层返回的过程中,longjmp 不会释放任何 VLA,如果它们的生命周期以此方式终止,可能会发生内存泄漏:

void g(int n)
{
    int a[n]; // a may remain allocated
    h(n); // does not return
}
void h(int n)
{
    int b[n]; // b may remain allocated
    longjmp(buf, 2); // might cause a memory leak for h's b and g's a
}
(自 C99 起)

参数

env - 指向由 setjmp
status - 从 setjmp 返回的值。如果它等于 0,1 则使用该值。

注意

longjmp 用于处理函数无法正常返回的意外错误情况。这类似于其他编程语言中的异常处理。

示例

#include <setjmp.h>
#include <stdio.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

参考文献

  • C23 标准 (ISO/IEC 9899:2024):
  • 7.13.2.1 longjmp 宏 (p: 283-284)
  • 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 宏 (p: 244-245)
  • C89/C90 标准 (ISO/IEC 9899:1990):
  • 4.6.2.1 longjmp 函数

参见

保存上下文
(函数宏)
C++ 文档 关于 longjmp