如何通过CLR访问C#堆栈?

bud*_*ble 5 c# heap clr stack cil

这可能是一个非常简单的问题,但我在SO上找不到答案,也不知道有人问我答案:

我可以写一个简单的c#方法,如下所示:

private void foo()
{
   int a = 1;
   int b = 5;
}
Run Code Online (Sandbox Code Playgroud)

如果CIL-Code(由编译器创建)由公共语言运行时执行,它将在堆栈顶部创建以下字段,而执行控件在方法内:

b = 5
a = 1
Run Code Online (Sandbox Code Playgroud)

但是现在,我扩展了Method来访问名为"a"的字段:

private void foo()
{
   int a = 1;
   int b = 5;
   Console.WriteLine(a);
}
Run Code Online (Sandbox Code Playgroud)

现在CLR必须访问不在堆栈顶部的字段,但根据FILO(先进先出)原则,它必须在访问之前处理请求字段之上的所有字段.

名为"b"的字段会在请求字段"a"上方的堆栈上发生什么?

CLR无法删除它,因为之后执行方法可能会使用它,那么会发生什么呢?

AFAIK,只有两种方法来存储字段,堆栈或堆.将它移到堆中将没有多大意义,因为这将从CLR堆叠中获得所有好处.CLR是否会创建类似第二个堆栈的东西?

这是如何工作的?

-编辑-

也许我没有清楚地解释我的意图.

如果我写一个像这样的方法:

private void foo()
{
   int a = 1;
   int b = 5;
   Console.WriteLine(a);
   Console.WriteLine(b);
}
Run Code Online (Sandbox Code Playgroud)

CLR首先在堆栈上写入2个字段,然后以相反的顺序访问它们.

首先,它必须访问字段"a",但为了达到它,CLR必须处理位于堆栈上字段"a"之上的字段"b".它不能从堆栈中删除字段"b",因为它必须在之后访问它.

这是如何运作的?

Dan*_*zey 6

变量不是单独堆叠的; 堆栈包含"框架".每个帧包含当前方法调用所需的所有变量(本地,参数等).因此,在您的示例中,a并且b在同一帧中彼此并存,并且不需要删除它们中的任何一个.当方法foo完成时,整个堆栈帧从堆栈中弹出,将调用方法的帧保留在顶部.

维基百科文章可能会提供一些启示.


jer*_*enh 3

请注意,当您谈论fields时,ab被称为局部变量

也许下面的简化逻辑表示可以澄清事情。在调用之前Console.WriteLine,堆栈顶部将如下所示:

|5| // b
|1| // a
Run Code Online (Sandbox Code Playgroud)

在 内部Console.WriteLine,为其参数添加了一个额外的堆栈帧(称为value,它获取变量 的副本a):

|1| // value = a
|5| // b
|1| // a
Run Code Online (Sandbox Code Playgroud)

一旦 Console.WriteLine 返回,顶部框架将被弹出,堆栈再次变为:

|5| // b
|1| // a
Run Code Online (Sandbox Code Playgroud)