在一切之前检查@PeterCordes 不仅仅以一种方式回答了这个问题
好吧,让我们开始吧:
这种类型的事情可以使用称为long jump
所以编辑后你的代码将如下所示:
#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");
}
让我们了解一下刚刚发生了什么
在上面的程序中,setjmp()
将当前执行环境保存在jmp_buf
结构和returns 0
.
程序继续调用A()
,这称为B()
.
尽管
在函数中B()
,如果用户选择不返回long jump
,函数将
显示正常的返回顺序。
如果用户选择返回longjmp(env,1234)
,
执行将返回到最后保存的环境nonzero
value.
在
这种情况,会导致B()
返回到main()
直接绕过A()
.
原理long jump
很简单。当一个函数完成时,它返回
(caller_EIP, caller_EBP)
在当前堆栈帧中,
如果我们更换(caller_EIP, caller_EBP)
with
(saved_EIP, saved_EBP)
较早函数的
在调用序列中,执行将直接返回到该函数。
此外
到(saved_EIP, saved_EBP)
, setjmp()
还可以保存CPU的通用寄存器和
原来的ESP
, 以便longjmp()
可以恢复返回的完整环境
功能。
长跳转可用于中止调用序列中的函数,从而导致
从先前保存的已知环境恢复执行。
虽然很少使用
在用户模式程序中,这是系统编程中的常用技术。
例如,
它可以用在信号捕捉器中来绕过导致的用户模式功能
异常或陷阱错误。
你可以检查this http://www.cplusplus.com/reference/csetjmp/longjmp/也不错