7

ECMA-335, I.12.3.2.4 states the following:

Part of each method state is a local memory pool. Memory can be explicitly allocated from the local memory pool using the localloc instruction. All memory in the local memory pool is reclaimed on method exit, and that is the only way local memory pool memory is reclaimed (there is no instruction provided to free local memory that was allocated during this method invocation). The local memory pool is used to allocate objects whose type or size is not known at compile time and which the programmer does not wish to allocate in the managed heap. Because the local memory pool cannot be shrunk during the lifetime of the method, a language implementation cannot use the local memory pool for general-purpose memory allocation.

Where does CLR allocate this memory pool? Is it managed heap, thread stack, etc?

4

1 回答 1

9

这都是故意模糊的,因为它是 CLI 规范不想确定的强大的实现细节。它窥视了Opcodes.Localloc的 MSDN 文章中的裂缝:

如果没有足够的内存来处理请求,则会引发 StackOverflowException。

获得 SOE 只有一种方法:它需要从堆栈中分配。

C# 语言在分配位置方面不太害羞,它使用stackalloc关键字。一个示例程序:

class Program {
    static unsafe void Main(string[] args) {
        int* p = stackalloc int[42];
    }
}

产生这个 IL:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       9 (0x9)
  .maxstack  8
  IL_0000:  ldc.i4.s   42
  IL_0002:  conv.u
  IL_0003:  ldc.i4.4
  IL_0004:  mul.ovf.un
  IL_0005:  localloc                   // <=== Here
  IL_0007:  pop
  IL_0008:  ret
} // end of method Program::Main

在运行时生成此机器代码:

02E42620  push        ebp  
02E42621  mov         ebp,esp  
02E42623  sub         esp,8  
02E42626  mov         dword ptr [ebp-4],esp  
02E42629  mov         dword ptr [ebp-8],6A029823h  
02E42630  mov         eax,esp  
02E42632  test        dword ptr [esp],esp  
02E42635  sub         eax,0A8h                       // <=== Here
02E4263A  mov         esp,eax  
02E4263C  mov         dword ptr [ebp-4],esp  
02E4263F  cmp         dword ptr [ebp-8],6A029823h  
02E42646  je          02E4264D  
02E42648  call        730CA5C0  
02E4264D  lea         esp,[ebp]  
02E42650  pop         ebp  
02E42651  ret  

sub eax,0A8h指令从ESP寄存器(堆栈指针)中减去0xa8 = 168 = 42x4字节,该mov esp,eax指令调整堆栈指针。所以是的,这肯定来自堆栈。

于 2013-10-27T15:37:11.497 回答