C# CLR在哪里分配本地内存池?

C# CLR在哪里分配本地内存池?,c#,.net,memory-management,clr,C#,.net,Memory Management,Clr,ECMA-335,I.12.3.2.4规定如下: 每个方法状态的一部分是本地内存池。可以使用localloc指令从本地内存池显式分配内存。在方法退出时回收本地内存池中的所有内存,这是回收本地内存池内存的唯一方法(没有提供用于释放此方法调用期间分配的本地内存的指令)。本地内存池用于分配在编译时类型或大小未知且程序员不希望在托管堆中分配的对象。由于本地内存池在方法的生命周期内无法收缩,因此语言实现无法将本地内存池用于通用内存分配 CLR在哪里分配此内存池?它是托管堆、线程堆栈等吗?这都是故意含糊其辞

ECMA-335,I.12.3.2.4规定如下:

每个方法状态的一部分是本地内存池。可以使用
localloc
指令从本地内存池显式分配内存。在方法退出时回收本地内存池中的所有内存,这是回收本地内存池内存的唯一方法(没有提供用于释放此方法调用期间分配的本地内存的指令)。本地内存池用于分配在编译时类型或大小未知且程序员不希望在托管堆中分配的对象。由于本地内存池在方法的生命周期内无法收缩,因此语言实现无法将本地内存池用于通用内存分配


CLR在哪里分配此内存池?它是托管堆、线程堆栈等吗?

这都是故意含糊其辞的,因为它是CLI规范不想明确的一个强大的实现细节。它从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
.method private隐藏静态void Main(字符串[]args)cil托管
{
.入口点
//代码大小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//我不能说有任何权限,但对我来说这听起来像是堆栈分配。然而,我怀疑该标准没有明确要求这样做,以便为实现者提供更大的灵活性。
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