问题
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);
}
}
回答1:
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 The longjmp function
2 The
longjmp
function restores the environment saved by the most recent invocation of thesetjmp
macro in the same invocation of the program with the correspondingjmp_buf
argument. If there has been no such invocation, [...] or if the function containing the invocation of thesetjmp
macro has terminated execution248) in the interim [...] the behavior is undefined.248) For example, by executing a
return
statement or because anotherlongjmp
call has caused a transfer to asetjmp
invocation in a function earlier in the set of nested calls.
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.
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.
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.
来源:https://stackoverflow.com/questions/51545566/why-a-segmentation-fault-occurs-calling-a-function-inside-setjmp