繁体   English   中英

为什么setjmp/longjmp

[英]Why does setjmp/longjmp

我想使用 setjmp/longjmp 在主函数中重用一些代码(注意:这只是一个练习,而不是我在现实世界中认真计划做的事情)。 以下代码是我想出的:

#include <stdio.h>
#include <setjmp.h>
jmp_buf jmp_body, jmp_ret;
    
void func(void)
{
    if (setjmp(jmp_ret) == 0)
        longjmp(jmp_body, 1);
}

int main()
{
    int x = 0;
    if (setjmp(jmp_body) == 1) {
        printf("Body %d\n", ++x);
        longjmp(jmp_ret, 1);
    }
    func();
    func();
    func();
    return 0;
}

我期望此代码的工作方式如下:

  1. main()函数将记住“body”部分的位置并使用if (setjmp(jmp_body) == 1)跳过它。
  2. 在使用if (setjmp(jmp_ret) == 0)记住主体应该返回的位置后, func()调用将使用longjmp(jmp_body)临时跳转到主体
  3. 主体将执行并使用longjmp(jmp_ret, 1)跳转回func()调用
  4. func() main()将按预期返回main()

因此,我期望打印的代码如下:

Body 1
Body 2
Body 3

相反,它永远循环不断地执行主体,这向我表明func()调用没有返回它应该返回的位置,而是可能返回到它自己之上,一遍又一遍地执行自己。

相比之下,以下代码打印的正是我所期望的:

#include <stdio.h>
#include <setjmp.h>
jmp_buf jmp_body, jmp_ret;

int main()
{
    int x = 0;
    if (setjmp(jmp_body) == 1) {
        printf("Body %d\n", ++x);
        longjmp(jmp_ret, 1);
    }
    if (setjmp(jmp_ret) == 0)
        longjmp(jmp_body, 1);
    if (setjmp(jmp_ret) == 0)
        longjmp(jmp_body, 1);
    if (setjmp(jmp_ret) == 0)
        longjmp(jmp_body, 1);
    return 0;
}

if (setjmp(jmp_ret) == 0) longjmp(jmp_body, 1)放在使原始方法无效的函数调用中是什么意思?

TL/DR - 你不能跳回你跳出的函数。

7.13.2.1 longjmp函数
...
2 longjmp函数使用相应的jmp_buf参数在程序的同一调用中恢复最近一次调用setjmp宏所保存的环境。 如果没有这样的调用,或者如果调用来自另一个执行线程,或者如果包含setjmp宏调用的函数在中间终止了执行248) ,或者如果setjmp宏的调用在具有可变修改类型和执行的标识符的范围在此期间离开了该范围,行为是 undefined
248) 例如,通过执行 return 语句或因为另一个longjmp调用已导致转移到嵌套调用集中较早的函数中的setjmp调用。
C 2011 在线选秀

当你执行longjmp(jump_body, 1); func ,您使jump_ret无效

longjmp不是双向的 - 它展开堆栈,就好像setjmplongjmp之间的任何函数调用从未发生过一样

您试图将longjmpmain()堆栈返回到func() 这个没有定义。 由于longjmp本身就是一个函数,您很可能最终将longjmp放入func ,返回地址是longjmp调用本身,因此是一个无限循环。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM