编译器如何知道函数调用后控制应该返回到哪里?
How does the compiler know where control should return to after a function call?
考虑以下函数:
int main()
{
//statement(s);
func1();
//statement(s);
}
void func1()
{
//statement(s);
func2();
//statement(s);
}
void func2()
{
//statement(s);
}
编译器如何知道在func2
执行了所有操作后返回到哪里?我知道控制转移到函数func1
(以及确切的哪个语句),但是编译器如何知道它?什么告诉编译器返回到哪里?
这通常使用调用堆栈:
实现- 当控制被转移到一个函数时,返回的地址被压入堆栈。 当函数结束时,该地址从堆栈中弹出,并用于将控制权转移回被调用方。
详细信息通常由编译代码的硬件体系结构强制执行。
实际上,编译器不运行代码,但是机器运行代码,当它调用一个新函数时,它将下一个指令的地址存储在当前被调用的函数之后的堆栈中,因此当函数返回时,它可以将其弹出回指令指针(IP)并从那里恢复。
为了便于解释,我做了一些简化。
当调用函数时,调用函数中的正确返回地址被放置在某个地方,通常是堆栈(尽管标准没有强制这样做),堆栈正是用于存储返回地址的目的。
编译器有责任确保它的调用约定是这样的,除非出现错误(例如,堆栈溢出),那么被调用的函数知道如何返回到调用函数。
运行时使用了一些被称为'调用堆栈'的东西,它基本上保存了被调用函数返回后要调用的下一个语句的地址。因此,当进行函数调用时,在控制跳转到新指令地址之前,调用函数中的下一个指令地址被推入堆栈。这个过程在以后对任何函数的每次调用中都要重复。为什么只有一堆呢?因为它需要回到它离开的地方,这基本上是一个'后进先出'的行为,堆栈是做那个的数据结构。当你在Visual Studio中调试一个程序时,你可以看到这个调用堆栈——有一个叫做"调用堆栈"的单独窗口,它显示了放置在调用堆栈中的地址项。
相关文章:
- 有人知道为什么在开关中使用stoi函数会返回恒定的错误吗
- 返回给定 SEXP 的子集,而无需知道实际的内部数据类型
- 创建一个始终返回零但优化器不知道的函数
- 当我使用按引用返回时,我不知道这些代码之间的区别
- 如何知道 sqlite 中的函数"回调"是否返回了一些东西?
- 任何人都知道如何解决尝试将从MySQL数据库返回的行打印到文本文件(.txt)中的C++
- 我的bool函数一直返回true,我不知道为什么
- rename()返回-1.如何知道重命名失败的原因
- C++ SQLite3 如何知道是否选择返回 0 行
- 如果向量包含重复项,则此函数应返回 true。知道为什么它不起作用吗?
- 如何使用 dlsym() 调用函数,如果我不知道返回类型和参数
- 不知道如何从气泡排序函数返回值
- 函数的调用方如何知道是否使用了返回值优化
- C++,我不知道为什么我的函数不返回结果
- 我的返回语句有一个错误,我不知道要修复
- c++返回多个表,如何知道返回表的名称
- 当返回一个集合指针时,客户端如何知道它是否需要销毁它?
- 不知道为什么我的函数一直返回相同的值
- 编译器如何知道函数调用后控制应该返回到哪里?
- python脚本能知道C++主函数在Android环境中的返回值吗