我想使用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;
}
我期望此代码的工作方式如下:
main()
函数将记住"身体"部分的位置,并使用if (setjmp(jmp_body) == 1)
跳过它- 在使用
if (setjmp(jmp_ret) == 0)
记住主体应该返回的位置之后,func()
调用将使用longjmp(jmp_body)
临时跳转到主体 - 主体将使用
longjmp(jmp_ret, 1)
执行并跳回func()
调用 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.1C 2011联机草稿longjmp
函数
2 nbsp nbsp;longjmp
函数恢复最近调用setjmp
宏在相同的程序调用中jmp_buf
自变量。如果没有这样的调用,或者调用来自另一个执行线程,或者如果包含setjmp
调用的函数宏已终止执行248(在过渡期间,或者如果调用setjmp
宏在具有可变修改类型的标识符的范围内,并且执行具有在过渡期间保留该范围,行为未定义。
248(例如,通过执行return语句或,因为另一个longjmp
调用导致转移到嵌套调用集中较早的函数中的CCD_ 19调用
当您在func
中执行longjmp(jump_body, 1);
时,会使jump_ret
无效。
longjmp
不是双向的——它展开堆栈,就好像setjmp
和longjmp
之间的任何函数调用都从未发生过一样。
您尝试将longjmp
从main()
回退到func()
。未对此进行定义。由于longjmp
本身就是一个函数,所以您很可能最终将longjmp
转换为func
,返回地址是longjmp
调用本身,因此是一个无限循环。