Reputation: 57
In a sequence of function calls, such as
main() --> A() --> B()-->C();
when a called function finishes, it normally returns to the calling function, e.g. C()
returns to B()
, which returns to A()
, etc.
i'm wondering if it is also possible to return directly to an earlier function in the calling sequence
so C()
return to main()
and skip B()
and A()
if it is possible how can i do it ? and can you explain how it work and when it used in reality.
this is my code
#include <stdio.h>
int A(void);
int B(void);
void main(void )
{
A();
}
int A()
{
printf("enter A()\n");
B();
printf("exit A()\n");
}
int B()
{
printf("enter B()\n");
printf("exit B()\n");
}
and i want to skip return to function A()
from B()
so that the printf("exit A()\n");
will not execute and give me this result:
enter A()
enter B()
exit B()
Upvotes: 3
Views: 564
Reputation: 3502
before everything check out @PeterCordes is answers the question in more than a way
okey let's start :
this type of stuff can be done using something known as long jump
so your code after editing will look like this :
#include <stdio.h>
#include <setjmp.h>//c standard library header
jmp_buf env; // for saving longjmp environment
main()
{
int r, a=100;
printf("call setjmp to save environment\n");
if ((r=setjmp(env)) == 0){
A();
printf("normal return\n");
}
else
printf("back to main() via long jump, r=%d a=%d\n", r, a);
}
int A()
{
printf("enter A()\n");
B();
printf("exit A()\n");
}
int B()
{
printf("enter B()\n");
printf("long jump? (y|n) ");
if (getchar()=='y')
longjmp(env, 1234);
printf("exit B()\n");
}
let's understand what just happened
In the above program, setjmp()
saves the current execution environment in a jmp_buf
structure and returns 0
.
The program proceeds to call A()
, which calls B()
.
While
in the function B()
, if the user chooses not to return by long jump
, the functions will
show the normal return sequence.
If the user chooses to return by longjmp(env,1234)
,
execution will return to the last saved environment with a nonzero
value.
In
this case, it causes B()
to return to main()
directly, bypassing A()
.
The principle of
long jump
is very simple. When a function finishes, it returns by the
(caller_EIP, caller_EBP)
in the current stack frame,
If we replace (caller_EIP, caller_EBP)
with
(saved_EIP, saved_EBP)
of an earlier function
in the calling sequence, execution would return to that function directly.
In addition
to the (saved_EIP, saved_EBP)
, setjmp()
may also save CPU’s general registers and the
original ESP
, so that longjmp()
can restore the complete environment of the returned
function.
Long jump can be used to abort a function in a calling sequence, causing execution to resume from a known environment saved earlier.
Although rarely used in user mode programs, it is a common technique in systems programming.
For example, it may be used in a signal catcher to bypass a user mode function that caused an exception or trap error.
you can check this is also good
Upvotes: 3