c# - 函数的返回值存储在哪里

标签 c# clr

我读过几篇关于堆栈、堆以及它们如何用于程序执行的文章。 Here是其中之一。 人们总是说调用一个函数时,它的参数和局部变量都被放置在堆栈中(严格地说这是不正确的,正如 Eric Lippert 在 his post 中所描述的,但这不是我现在的问题)。

我的问题是函数的返回值存储在哪里以及它如何传递给调用者?没有人说它放在堆栈上,但仍然没有人说它不是。谁能澄清一下?

例如,考虑以下函数:

public DateTime GetTomorrowDate()
{
    return DateTime.Now.AddDays(1).Date;
}

我的理解是它将为返回值声明一个局部变量是否正确?如果是这样,为什么当函数返回时它没有被销毁并且它的堆栈框架被销毁了?它是否在调用者的堆栈帧中声明(即使它没有被调用者使用)?或者它可能存储在寄存器中的某个地方(我不相信,因为对于某些自定义结构可能没有合适大小的寄存器)。

最佳答案

有几种策略(我已经使用过)。

  1. 返回值足够小,可以放入一个寄存器中,并且作为一个值从函数返回到一个为该目的保留的寄存器中。如果需要,这可以扩展到 2 个或更多寄存器。
  2. 返回值作为临时变量创建在调用者 的栈帧中。然后将临时对象的引用(指针)压入堆栈,以便返回值充当额外的输出参数。在某些语言中,该变量作为命名变量(“结果”)出现在被调用函数中,而在其他语言中,编译器会生成对该参数的移动。
  3. 创建了两个局部变量,一个在函数内部,一个在函数外部。在函数退出时将值从一个复制到另一个。
  4. 返回值只是作为一个额外的参数创建的。在该参数中找到的值在展开堆栈之前由调用者提取。
  5. 值在“特殊”寄存器中返回,例如浮点累加器。
  6. 该值被放置在一个已知位置(例如任务框架),以后可以从中检索它。

可能还有其他的,但这是一个好的开始。


我的回答是基于阅读这个问题,因为它想要一个常用技术的总结。在 C# 的上下文中,它适用于 JIT 生成的代码,但不适用于 CIL 本身。

典型的面向堆栈的 VM 语言(包括 CIL)主要通过在函数返回时将它们留在堆栈中来从函数返回值。参数位于其下方,因此在函数返回后需要进行一些堆栈清理。

正如@eric 所说,很难看出这些信息何时有用。显然,从函数返回大值类型可能会对性能产生影响,但这只是预期的结果。

CIL 有很好的文档记录,但 JIT 编译和可能的其他机制没有,这将进一步降低任何此类见解的有用性。

关于c# - 函数的返回值存储在哪里,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25162192/

相关文章:

c# - 有什么叫做列表数组的东西吗?

c# - Quartz.net + 任务并行库

C# 文件并从 1 自动重命名?

c# - 调用接口(interface)成员的虚方法的CLR实现

c# - 使用 .net WebClient 访问交叉签名的 SSL 服务

c# - 调用 jGrowl 时,thickbox 停止正常工作(使用 UpdatePanel)

c# - 为什么 BeforeFieldInit 行为在 .NET 4 中发生了变化?

sql - 注册 SQL CLR 存储过程中使用的程序集

.net - 使用不同的.Net 语言?

regex - 分数的 CLR 正则表达式