为什么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;
}
我期望此代码的工作方式如下:
- 该
main()函数将记住“主体”部分的位置并使用if (setjmp(jmp_body) == 1). - 在记住主体应该返回的位置之后,
func()调用将暂时跳转到主体longjmp(jmp_body)usingif (setjmp(jmp_ret) == 0) - 主体将执行并跳转回
func()调用使用longjmp(jmp_ret, 1) - 该
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.1
longjmp函数
...
2 该longjmp函数setjmp使用相应的jmp_buf参数,在程序的同一调用中恢复最近一次宏
调用所保存的环境。如果没有这样的调用,或者如果调用来自另一个执行线程,或者如果包含setjmp
宏调用的函数在中间终止了执行248),或者如果setjmp
宏的调用在具有可变修改类型和执行的标识符在此期间离开了该范围,行为是 undefined。
248) 例如,通过执行 return 语句或因为另一个
longjmp调用已导致转移到setjmp嵌套调用集中较早的函数中的调用。
C 2011 在线选秀
当您执行longjmp(jump_body, 1);in 时func,您就无效了 jump_ret。
longjmp不是双向的 - 它展开堆栈,就好像setjmp和longjmp 从未发生过的任何函数调用一样。