【发布时间】:2021-07-15 14:07:07
【问题描述】:
我想使用 setjmp/longjmp 来重用 main 函数中的一些代码(注意:这只是一个练习,并不是我在现实世界中认真计划做的事情)。 以下代码是我想出的:
#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;
}
我期望这段代码的工作方式如下:
-
main()函数将记住“body”部分的位置并使用if (setjmp(jmp_body) == 1)跳过它。 -
func()调用将在使用if (setjmp(jmp_ret) == 0)记住身体应该返回的位置后使用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 %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) 放在函数调用中会导致原始方法无效是什么原因?
【问题讨论】:
-
“暂时跳跃”是一个有趣的表达方式。没有什么是暂时的。当您跳出
func时,jump_rec不再有效。所以后续的长跳尝试是未定义的。 -
是的,我认为您误解了
longjmp是什么以及做什么。您只能跳上调用堆栈,进入尚未返回的函数。当你这样做时,你会隐式地从当前函数以及介于两者之间的所有函数返回;然后你不能 longjmp 回到他们身边。这不是为了在整个程序中跳转到随机的代码块;相反,它会强制堆栈上的多个函数同时返回,例如在支持它的语言中抛出异常。 -
longjmp()确实展开堆栈,展开部分中的所有内容都不再有效,您可以了解堆栈展开以及setjmp()和longjmp()的实际工作方式。请使用一致的意图风格。