Why a segmentation fault occurs calling a function inside setjmp()?

Multi tool use


Why a segmentation fault occurs calling a function inside 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.
middleFunc()
entry_point(arg)
if ( setjmp(middle) )
#include <stdio.h>
#include <setjmp.h>
jmp_buf start,middle,end;
void finalFunc(void *v)
{
printf("hellon");
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 Answer
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
).
middle
middleFunc
longjmp
7.13.2.1 The longjmp function
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.
longjmp
setjmp
jmp_buf
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.
return
longjmp
setjmp
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.
middleFunc
middle
main
longjmp(start,1)
middle
middle
setjmp/longjmp
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
entry_point
entry_point
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/longjmp
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
thank you, is this the reason for which co-rotuine are implemented with a new allocated stack ?
– Neo
2 mins ago