一段代码在这里
jmp_buf mark;
int Sub_Func()
{
int be_modify, jmpret;
be_modify = 0;
jmpret = setjmp( mark );
if( jmpret == 0 )
{
// sth else here
}
else
{
// error handle
switch (jmpret)
{
case 1:
printf( "Error 1n");
break;
case 2:
printf( "Error 2n");
break;
case 3:
printf( "Error 3n");
break;
default :
printf( "Unknown Error");
break;
}
printf("after switchn");
}
return jmpret;
}
void main( void )
{
Sub_Func();
// the longjmp after setjmp
longjmp(mark, 1);
}
结果是:
错误 1
切换
后分段错误
我知道原因可能是 longjmp 跳回到上一个堆栈。 但我不确定细节,以及"标记"中存储了什么样的值,谁能解释一下?
setjmp()
并通过记录堆栈帧位置来longjmp()
工作。如果在 Sub_Func()
中记录堆栈帧,但在调用 longjmp()
之前从函数返回,则堆栈帧不再有效。 longjmp()
意味着在与 setjmp()
相同的函数中调用(子函数是可以的)。
您正在尝试将 longjmp 返回到更深层次的函数。您只能长 jmp 回到较浅的函数。
因此,如果 A 调用 setjmp
,然后调用 B,则 B 可以longjmp
回 A。
但如果A调用B,B调用setjmp
,B返回A,A不能longjmp
回B。
您通过违反以下 (7.13.2.1) 调用了未定义的行为:
longjmp 函数使用相应的 jmp_buf 参数恢复最近一次调用 setjmp 宏时保存的环境。如果没有这样的调用,或者包含 setjmp 宏调用的函数在此期间终止了 execution217),或者如果 setjmp 宏的调用在具有可变修改类型的标识符的范围内,并且执行在此期间离开了该范围,则行为是未定义的。
217) 例如,通过执行 return 语句,或者因为另一个 longjmp 调用导致在嵌套调用集中较早的函数中转移到 setjmp 调用。
简而言之,longjmp
不能用于跳转到已返回的函数中的setjmp
点。