【发布时间】:2018-08-19 04:54:03
【问题描述】:
在一系列函数调用中,比如
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()
【问题讨论】:
-
除非你使用
setjmp/longjmp,否则你不能在 C 中使用。或者你可以让B()调用exit()而不是返回。如果这是 C++,您可以使用 try/catch 和异常将堆栈展开回main(),如果已编译main以支持它(通过使用try/catch。 -
为什么要标记这个 x86 程序集?您是否想让
B()jmp 直接到main的末尾,而不管它是从哪里调用的。我猜理论上对于特定平台,您可以展开堆栈并获取您父母的返回地址,但这对于 Linux 与 Windows 的工作方式不同,例如在 Linux 上使用.eh_frame元数据。对于简单的示例,它可能会在某些时候起作用。 -
请注意,
main()可能已编译为使用jmp A尾调用 A,因为您将其声明为void。此外,您的程序具有未定义的行为:您脱离了非 void 函数 A() 和 B() 的末尾。而void main(void)不是有效的函数签名之一是 ISO C:int main(void)是合法的。void main()可以在 x86 的普通编译器上工作,你只会得到一个垃圾退出状态。 -
我使用intel pc这就是x86标签的原因
-
我想我们可能会在这里讨论一个 XY 问题meta.stackexchange.com/questions/66377/what-is-the-xy-problem 我的意思是,如果您退后一步并通过跳过部分回报来描述您想要实现的目标,您可能会得到更好的帮助小路。你想用这个机制做什么?如果您对此进行描述,它可能可以通过不同的方式实现,这些方式更容易理解和/或更广泛使用(这意味着您将学到一些可以更好地用于其他问题的东西)。