本地变量在CLR中实际分配在哪里? [英] Where does local variables actually allocated within CLR?

查看:51
本文介绍了本地变量在CLR中实际分配在哪里?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是进入CLR和IL之内,对此事感到困惑.

我有以下C#代码:

  int x = 1;对象obj = x;int y =(int)obj; 

IL为此为此拆卸了

 //代码大小18(0x12).maxstack 1.locals init([0] int32 x,[1]对象obj,[2] int32 y)IL_0000:不IL_0001:ldc.i4.1IL_0002:stloc.0IL_0003:ldloc.0IL_0004:框[mscorlib] System.Int32IL_0009:stloc.1IL_000a:ldloc.1IL_000b:unbox.any [mscorlib] System.Int32IL_0010:stloc.2IL_0011:退回 

因此, ldloc.0 指令将索引0的局部变量加载到堆栈上".但是当地人真正存储在哪里以及从何处加载.因为我认为可以在两个地方分配内存:线程堆栈和堆.并且变量应存储在堆栈中.

现在,我想,堆栈只是一个评估堆栈",而变量的内存分配是一个实现细节,并取决于平台和JIT编译器.实际上,我们可以在评估堆栈,托管堆和本地分配的内存上拆分程序所使用的内存.

这是真的吗?还是这里有其他机制?

解决方案

您正在严格混淆许多逻辑上不同的东西:

  • 仅仅因为变量是C#中的局部变量,并不意味着它在IL中的短期存储池中.C#中的局部变量可以对应于相应IL中的短期存储,长期存储或评估堆栈.
  • IL中的短期存储和评估堆栈可以对应于固定机器代码中的堆栈或寄存器存储.

在将C#编译为IL时,C#编译器使本地人成为闭包类的成员 –他们进入长期存储池–当本地人的生存期更长时[em]而不是激活方法.(或者当方法的激活被分解为小块时,就像在异步方法中一样.)

如果本地人的生存期很短,那么编译器的优化器将选择他们是进入短期池还是进入评估堆栈;编译器将后者称为临时"本地人.决定何时将本地化为临时数据库的算法很有趣;有关详细信息,请参见编译器源代码.

然后,抖动必须决定是否将短期池变量和评估堆栈变量放入堆栈位置或寄存器中;它会使用复杂的优化算法再次执行此操作,该算法会根据寄存器的可用性等而变化.

最后,当然,C#编译器和抖动都可以自由地将未读的本地化为一无所有.从未分配过从未读取过的存储空间.

I'm just going inside the CLR and IL and I'm confused by this thing.

I have the following C# code:

int x = 1;
object obj = x;
int y = (int)obj;

And IL disassemble for this

      // Code size       18 (0x12)
  .maxstack  1
  .locals init ([0] int32 x,
           [1] object obj,
           [2] int32 y)
  IL_0000:  nop
  IL_0001:  ldc.i4.1
  IL_0002:  stloc.0
  IL_0003:  ldloc.0
  IL_0004:  box        [mscorlib]System.Int32
  IL_0009:  stloc.1
  IL_000a:  ldloc.1
  IL_000b:  unbox.any  [mscorlib]System.Int32
  IL_0010:  stloc.2
  IL_0011:  ret

So, the ldloc.0 instruction "Loads the local variable at index 0 onto stack.". But where does the locals really stored and where does they loaded from. Because I thought that there are two places where the memory can be allocated: thread stack and heap. And variables should be stored in the stack.

Now, I suppose, that the stack is just an "evaluation stack", while the memory allocation for variables is an implementation detail and depend on platform and JIT compiler. And we actually can split the memory used by our programm on evaluation stack, managed heap, and locals allocated memory.

Is this true? Or there are some other mechanism here?

解决方案

You are severely conflating many things which are logically different:

  • Just because a variable is a local variable in C# does not mean that it is on the short term storage pool in IL. Local variables in C# can correspond to short term storage, long term storage, or evaluation stack in the corresponding IL.
  • Short term storage and evaluation stack in IL can correspond to stack or register storage in the jitted machine code.

When compiling C# to IL, the C# compiler makes locals members of a closure class -- they go on the long term storage pool -- when the lifetime of the local is possibly longer than the activation of the method. (Or when the activation of the method is broken up into little pieces, like it is in an async method.)

If the locals have short lifetimes then the compiler's optimizer chooses whether they go on the short term pool or the evaluation stack; the compiler calls the latter "ephemeral" locals. The algorithm for deciding when to make a local into an ephemeral is interesting; see the compiler source code for details.

The jitter then must decide whether to make short term pool variables and evaluation stack variables into stack locations or registers; it does so again using a complex optimization algorithm that varies depending on register availability and so on.

Finally, of course the C# compiler and the jitter are both free to reify an unread local as nothing at all; storage that is never read from need not actually be allocated.

这篇关于本地变量在CLR中实际分配在哪里?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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