【发布时间】:2014-08-06 13:52:01
【问题描述】:
我已经阅读了几篇关于堆栈、堆以及它们在程序执行中的使用方式的文章。 Here 就是其中之一。 总是说在调用函数时,它的参数和局部变量都被放入堆栈(严格来说这是不正确的,正如 Eric Lippert 在his post 中描述的那样,但这不是我现在的问题)。
我的问题是函数的返回值存储在哪里以及它如何传递给调用者?没有人说它放在堆栈上,但仍然没有人说它不是。谁能澄清一下?
例如,考虑以下函数:
public DateTime GetTomorrowDate()
{
return DateTime.Now.AddDays(1).Date;
}
我的理解是它会为返回值声明一个局部变量吗?如果是这样,为什么当函数返回并且堆栈帧被破坏时它没有被破坏?它是否在调用者的堆栈帧中声明(即使调用者没有使用它)?或者它可能存储在寄存器中的某个位置(我不相信,因为某些自定义结构可能没有合适大小的寄存器)。
【问题讨论】:
-
这些是实现细节。这个函数最终也可能被内联。
-
@Habib,问题不在于这个特定的功能。这只是一个例子。我的问题是了解 CLR 如何处理它。如果有不同的可能性 - 它们适用于哪些情况?
-
在幕后,返回值将被存储在一个寄存器中——在这种情况下,作为一个地址指向一个 DateTime 的底层实现。 CLR 将根据对返回对象的引用持有多长时间来管理对象的生命周期。
-
返回值存储在寄存器中 - 在 x64 上它进入 RAX。在 x86 上,像
DateTime这样的 64 位结构在 EAX:EDX 中返回。 -
在示例中,有一个 AddFive 方法。它的返回值到栈尾(因为 Int32 是值类型),和在 C/C++ 中的工作方式一样,没有太大区别。 DateTime 也是如此,因为它也是一种值类型。唯一的区别是它的大小更大,并且在堆栈中分配了更多空间。