函数的返回值存储在哪里 [英] Where is return value from function stored

查看:367
本文介绍了函数的返回值存储在哪里的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我读了几篇有关堆栈,堆以及它们如何在程序执行中使用的文章。 此处是其中之一。
总是说在调用函数时,它的参数以及局部变量都放在堆栈中(严格来说,这是不正确的,正如Eric Lippert在他的帖子,但这不是我的问题)。

I've read few articles about stack, heap and how they are used in program execution. Here is one of them. It is always said that when calling a function, it's parameters are placed to stack, as well as local variables (strictly saying that's not correct, as Eric Lippert described in his post, but that's not my question now).

我的问题是函数的返回值存储在哪里,以及如何将其传递给调用方?没有人说它被放在堆栈上,但是仍然没有人说不是。有人可以澄清吗?

My question is where the return value from function is stored and how is it passed to the caller? Nobody says it's placed on stack, but still nobody says it's not. Can anybody clarify that?

例如,考虑以下函数:

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

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

Is my understanding that it will declare a local variable for return value correct? If so, why it isn't destroyed when function returns and it's stack frame destroyed? Is it declared in the caller's stack frame (even if it is not used by a caller)? Or maybe it is stored somewhere in a register (I don't believe that, because there may be not suitable-size register for some custom structure).

推荐答案

(我使用过)几种策略。

There are several strategies (that I have used).


  1. 返回值足够小以适合寄存器,并从函数中作为为此保留的寄存器中的值返回。如果需要,可以将其扩展到2个或更多寄存器。

  2. 返回值被创建为调用方的堆栈框架上的临时变量。然后将对临时变量的引用(指针)压入堆栈,以便返回值充当额外的out参数。在某些语言中,变量以命名变量(结果)的形式出现在调用的函数中,在另一些语言中,编译器将移动到该参数。

  3. 创建了两个局部变量,一个在内部功能和外部。该值在函数退出时从一个复制到另一个。

  4. 返回值只是作为一个额外的参数创建的。

  5. 在该参数中找到的值在被释放之前由调用者取出。

  6. 该值在特殊寄存器中返回,例如浮点累加器。

  7. 该值放置在已知位置(例如任务框架),以后可以从中取值。

  1. The return value is small enough to fit into a register, and is returned from the function as a value in a register reserved for that purpose. This can be extended to 2 or more registers if needed.
  2. The return value is created as a temporary variable on the stack frame of the caller. Then a reference (pointer) to the temporary is pushed on the stack so that the return value acts as an extra, out parameter. In some languages that variable appears inside the called function as a named variable ('result'), in others the compiler generates a move to that parameter.
  3. Two local variables are created, one inside the function and one outside. The value is copied from one to the other on function exit.
  4. The return value is simply created as an extra argument. The value found in that argument is pulled out by the caller before it unwinds the stack.
  5. The value is returned in a 'special' register, such as a floating point accumulator.
  6. The value is placed in a known location (such as a task frame), from which it can be retrieved later.

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

There are probably others, but those are a good start.

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

My answer was based on reading the question as wanting a summary of common techniques. In the context of C# it would apply to JIT-generated code, but not the CIL itself.

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

Typical stack-oriented VM languages (including CIL) return values from functions primarily by leaving them on the stack when the function returns. The arguments sit below that, so some stack cleanup is required after function return.

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

As @eric says, it's hard to see when this information might be useful. Obviously returning large value types from functions could have performance implications, but that is only as expected.

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

The CIL is rather well documented, but JIT compilation and possible other mechanisms are not, which would further reduce the usefulness of any such insights.

这篇关于函数的返回值存储在哪里的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆