存储函数的返回值在哪里

时间:2014-08-06 13:52:01

标签: c# clr

我读过很多关于堆栈,堆以及如何在程序执行中使用它们的文章。 Here就是其中之一。 总是说,在调用一个函数时,它的参数被放置到堆栈,以及局部变量(严格说这不正确,正如Eric {{{{{{{{}}中描述的那样,但是& #39;现在不是我的问题了。)

我的问题是哪里存储了函数的返回值以及如何将其传递给调用者?没有人说它被置于堆栈中,但仍然没有人说它是什么不。任何人都可以澄清一下吗?

例如,请考虑以下函数:

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

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

1 个答案:

答案 0 :(得分:1)

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

  1. 返回值足够小以适合寄存器,并从函数返回,作为为此目的保留的寄存器中的值。如果需要,可以将其扩展到2个或更多寄存器。
  2. 返回值在调用者的堆栈帧上创建为临时变量。然后在堆栈上推送临时的引用(指针),以便返回值充当额外的out参数。在某些语言中,变量作为命名变量('result')出现在被调用函数内部,在其他语言中,编译器会生成对该参数的移动。
  3. 创建两个局部变量,一个位于函数内部,另一个位于外部。在函数出口处将值从一个复制到另一个。
  4. 返回值只是作为额外参数创建。调用者在解除堆栈之前将该参数中找到的值拉出。
  5. 该值在“特殊”寄存器中返回,例如浮点累加器。
  6. 可能还有其他人,但这些都是一个好的开始。


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

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

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

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