C语言 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 %dn", ++x);
longjmp(jmp_ret, 1);
}
func();
func();
func();
return 0;
}

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

  1. main()函数将记住"身体"部分的位置,并使用if (setjmp(jmp_body) == 1)跳过它
  2. 在使用if (setjmp(jmp_ret) == 0)记住主体应该返回的位置之后,func()调用将使用longjmp(jmp_body)临时跳转到主体
  3. 主体将使用longjmp(jmp_ret, 1)执行并跳回func()调用
  4. func()将按预期返回到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 %dn", ++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.1longjmp函数

2 nbsp nbsp;longjmp函数恢复最近调用setjmp宏在相同的程序调用中jmp_buf自变量。如果没有这样的调用,或者调用来自另一个执行线程,或者如果包含setjmp调用的函数宏已终止执行248(在过渡期间,或者如果调用setjmp宏在具有可变修改类型的标识符的范围内,并且执行具有在过渡期间保留该范围,行为未定义
248(例如,通过执行return语句或,因为另一个longjmp调用导致转移到嵌套调用集中较早的函数中的CCD_ 19调用
C 2011联机草稿

当您在func中执行longjmp(jump_body, 1);时,会使jump_ret无效。

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

您尝试将longjmpmain()回退到func()。未对此进行定义。由于longjmp本身就是一个函数,所以您很可能最终将longjmp转换为func,返回地址是longjmp调用本身,因此是一个无限循环。

最新更新