C - 在调用方的返回序列中跳过函数



在一系列函数调用中,例如

main() --> A() --> B()-->C();

当被调用函数完成时,它通常会返回到调用函数,例如C()返回B(),返回A(),等等。

我想知道是否也可以直接返回到调用序列中的较早函数 所以C()回到main(),跳过B()A()

如果可能的话,我该怎么做?你能解释一下它是如何工作的,以及它何时在现实中使用吗?

这是我的代码

#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");
}

我想从B()跳过返回到函数A(),以便printf("exit A()n");不会执行并给我这个结果:

enter A()                                                                                                                  
enter B()                                                                                                                  
exit B() 

在一切检查之前@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 environmentn");
if ((r=setjmp(env)) == 0){
A();
printf("normal returnn");
}
else
printf("back to main() via long jump, r=%d a=%dn", 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值。

在 在这种情况下,它会导致B()直接返回到main(),绕过A()

原理long jump非常简单。当一个函数完成时,它返回的

(caller_EIP, caller_EBP)在当前堆栈帧中, 如果我们用(caller_EIP, caller_EBP)替换

早期函数的(saved_EIP, saved_EBP)在调用序列中,执行将直接返回到该函数。

另外 对于(saved_EIP, saved_EBP)setjmp()也可以保存CPU的通用寄存器和 原始ESP,以便longjmp()可以恢复返回的完整环境 功能。

跳远可用于中止调用序列中的函数,导致 执行以从之前保存的已知环境恢复。

虽然很少使用 在用户模式程序中,它是系统编程中的常用技术。

例如 它可以在信号捕获器中用于绕过导致的用户模式功能 异常或陷阱错误。

你可以检查这个也很好

最新更新