Michael Kerrisk在“Linux编程接口”中的练习6.2问道:
编写程序,看看如果我们尝试
longjmp()
进入已经终止的函数会发生什么。
我在想这个程序应该可以解决问题:
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
static jmp_buf env;
void foo (void);
void bar (void);
void baz (void);
int
main (int argc, char *argv[])
{
foo();
bar();
exit(EXIT_SUCCESS);
}
void
foo (void)
{
printf("foo start\n");
switch (setjmp(env)) {
case 0:
printf("foo branch 0\n");
break;
case 1:
printf("foo branch 1\n");
break;
}
printf("foo end\n");
return;
}
void
bar (void)
{
printf("bar start\n");
baz();
printf("bar end\n");
return;
}
void
baz (void)
{
printf("baz start\n");
longjmp(env, 1);
printf("baz end\n");
return;
}
相反,这会打印:
$ ./setjmp
foo start
foo branch 0
foo end
bar start
baz start
foo branch 1
foo end
也就是说,如果foo
没有终止,我会期望的行为。这是为什么?如何修改我的程序以使longjmp
成为终止函数?
答案 0 :(得分:2)
Wikipedia。拿一粒盐。
跳转到已通过return或longjmp终止的函数 未定义。[6]但是,longjmp的大多数实现都没有 在执行跳转时专门销毁局部变量。从那以后 上下文一直存在,直到它的局部变量被删除,它可以 实际上是通过setjmp恢复的。
幸运的是,他们引用了(尽管是旧的)标准。
§7.13.2.1/ 2
longjmp函数恢复最近保存的环境 在同一个程序调用中调用setjmp宏 使用相应的jmp_buf参数。如果没有这样的话 调用,或者如果函数包含setjmp的调用 宏已在临时中终止执行 211),或者如果是 setjmp宏的调用是在标识符的范围内 具有可变修改类型和执行已经留下了该范围 临时,行为未定义。
211)例如,通过执行return语句或另一个语句 longjmp调用导致转移到a中的setjmp调用 在嵌套调用集的早期函数。