为什么在setjmp()中调用函数会发生分段错误?
我不明白为什么在函数middleFunc()
,当在if ( setjmp(middle) )
语句if ( setjmp(middle) )
调用entry_point(arg)
时,会出现分段错误。
#include #include jmp_buf start,middle,end; void finalFunc(void *v) { printf("hello\n"); return ; } void middleFunc(void (*entry_point)(void *), void *arg) { //just debug : this does not cause segmentation fault entry_point(arg); if ( setjmp(middle) ){ //this casues the segmentation fault entry_point(arg); //once the entry point (finalFunc) is executed go to jmp_buffer end longjmp(end,1); } else { longjmp(start,1); } } int main(){ if (setjmp(end)){ //exit since finalFunc has been executed return 0; } if (setjmp(start)){ //the middleFunc has previously set the jmp_buffer middle longjmp(middle,1); } else{ int x = 1; middleFunc(finalFunc,(void*)&x); } }
在您的代码中,行为是未定义的。 在middleFunc
完成执行后(通过正常完成或另一个longjmp
),不允许长跳到middle
。
7.13.2.1 longjmp函数
2
longjmp
函数在相同的程序调用中使用相应的jmp_buf
参数恢复最近调用setjmp
宏所保存的环境。 如果没有这样的调用,或者如果包含setjmp
宏调用的函数在临时[…]中终止执行248) ,则行为是未定义的。248)例如,通过执行
return
语句或因为另一个longjmp
调用导致在嵌套调用集合中较早的函数中转移到setjmp
调用。
在你的代码中, middleFunc
设置middle
,之后立即通过执行longjmp(start,1)
退出到main
。 之后,跳跃middle
不再有效。 你不再被允许从任何地方跳到middle
。 setjmp/longjmp
机制只支持跳转调用堆栈。 你不能做侧跳或下跳。 仅支持向上跳跃。
从实际的角度来看,您正试图跳转到“死”函数调用,并以某种方式期望函数参数值仍然有效(例如,从先前的调用或其他东西保留)。 但事实并非如此。 setjmp/longjmp
不保留/恢复参数值。 在“死”调用中entry_point
值可能是一些垃圾 。 当您尝试通过entry_point
进行呼叫时,代码coredumps。
PS确实用setjmp/longjmp
侧跳有时用于实现协同例程。 但是,这种使用超出了标准库规范的范围。 并且在任何情况下,这样的使用永远不会期望保存参数值。