为什么调用 setjmp() 中的函数会发生分段错误? [英] Why a segmentation fault occurs calling a function inside setjmp()?
问题描述
我不明白为什么在函数 middleFunc()
中,当 entry_point(arg)
在 if ( setjmp(中) )
语句.
I do not understand why in the function middleFunc()
, a segmentation fault is raisen when entry_point(arg)
is invoked inside the if ( setjmp(middle) )
statement.
#include <stdio.h>
#include <setjmp.h>
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
.
In your code the behavior is undefined. You are not allowed to long-jump to middle
after middleFunc
finished execution (either by normal completion or by another longjmp
).
7.13.2.1 longjmp 函数
2 longjmp
函数恢复最近一次调用 setjmp
宏时保存的环境对应的 jmp_buf
参数.如果没有这样的调用,[...] 或者如果包含 setjmp
宏调用的函数在中间 [...] 行为未定义.
2 The longjmp
function restores the environment saved by the most recent invocation of the setjmp
macro in the same invocation of the program with the corresponding jmp_buf
argument. If there has been no such invocation, [...] or if the function containing the invocation of the setjmp
macro has terminated execution248) in the interim [...] the behavior is undefined.
248) 例如,通过执行 return
语句或因为另一个 longjmp
调用已导致转移到函数中的 setjmp
调用在嵌套调用集中的较早位置.
248) For example, by executing a return
statement or because another longjmp
call has caused a transfer to a setjmp
invocation in a function earlier in the set of nested calls.
在您的代码中 middleFunc
设置 middle
,然后通过执行 longjmp(start,1)<立即退出到
main
/代码>.之后跳转 middle
不再有效.你不再被允许从任何地方跳转到 middle
.setjmp/longjmp
机制只支持向上跳转调用栈.你不能做侧跳或下跳.仅支持向上跳跃.
In your code middleFunc
sets up middle
and after that immediately exits to main
by doing longjmp(start,1)
. After that jump middle
is no longer valid. You are no longer allowed to jump to middle
from anywhere. setjmp/longjmp
mechanism only supports jumps up the call stack. You cannot do side-jumps or down-jumps. Only up-jumps are supported.
从实际的角度来看,您正试图跳入一个死"的函数调用,并以某种方式期望函数参数值仍然有效(例如,从先前的调用中保留下来或其他东西).但他们不是.setjmp/longjmp
不保存/恢复参数值.entry_point
在那个死"调用中的价值可能是一些垃圾一>.当您尝试通过 entry_point
进行调用时,代码核心转储.
From the practical point of view, you are attempting to jump into a "dead" function invocation and somehow expecting that function parameter values are still valid (like, preserved from the previous invocation or something). But they are not. setjmp/longjmp
do not preserve/restore parameter values. Value of entry_point
in that "dead" invocation is probably some garbage. When you attempt to make a call through entry_point
, the code coredumps.
附言确实,有时会使用 setjmp/longjmp
进行侧跳来实现协同例程.但是,这种用法超出了标准库规范的范围.在任何情况下,这种用法都不会期望保留参数值.
P.S. It is true that side-jumping with setjmp/longjmp
is sometimes used to implement co-routines. However, such usage falls outside the boundaries of standard library specification. And in any case such usage will never expect preservation of parameter values.
这篇关于为什么调用 setjmp() 中的函数会发生分段错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!