被调用的函数究竟什么时候结束

When exactly does a called function end?

本文关键字:什么时候 结束 究竟 函数 调用      更新时间:2023-10-16

在我读的一本教科书中,据说对于具有返回值的函数,返回值用于初始化调用站点上的临时函数。

我想知道的是,在被调用函数退出之前还是之后会发生这种情况?换句话说,如果我在被调用的函数中定义了一个变量(比如int),它会在临时初始化之前或之后被销毁吗?

这是技术视图。这对语言律师来说可能并不有趣,但对其他人来说,这可能对我很有启发性。


函数以将控制权转移回调用方的分支指令精确结束。在此之前,被调用者拥有完全控制权,在此之后,调用者拥有对CPU操作的完全控制权。通常,只有一条CPU指令用于此控制传输。在X86-64上,这是ret指令,PowerPC使用blr,其他CPU也有相同的名称。不过,名字并不重要。

函数本身职责范围内的任何事情都必须在该指令之前发生,任何与被调用者无关的事情都必须发生在其他地方。

由于调用方不知道函数创建了哪些变量,因此调用方不能负责销毁这些变量。更一般地说,被调用者必须释放它为自己的目的分配的任何堆栈空间。因此,被调用者必须在发出ret指令退出之前自行执行此类清理。这意味着,在函数退出之前,任何局部变量都必须消失。

当涉及到从函数返回结果时,事情就有点复杂了:这需要调用方和被调用方进行协作。不同的调用约定的细节不同,但通常有两种情况:

  1. 返回值在寄存器中传递
    在这种情况下,被调用者将返回值加载到一个已知的寄存器中,调用者将使用该寄存器访问返回值。

  2. 返回值在堆栈上传递。在这种情况下,被调用者将把要返回的数据放在调用者堆栈帧中的一个定义位置,并且调用者将在调用返回后检查同一内存区域中的函数结果。

TL;DR:如果某件事是函数的责任,那么它必须在函数返回(=执行ret指令)之前发生。释放堆栈空间和将数据返回给调用者就是这样的责任。

之前

对于按值返回的函数,在函数的作用域退出之前,调用站点上的临时将初始化。否则,任何返回值都将在传递到调用站点之前被销毁。

函数在返回语句后结束
在该作用域中声明的变量将超出作用域,除非变量声明为静态,否则您将无法使用它