ECMA-335,I.12.3.2.4规定如下:
每个方法状态的一部分是一个本地内存池。可以使用
localloc指令从本地内存池显式分配内存。本地内存池中的所有内存都是在方法退出时回收的,这是回收本地内存池内存的唯一方法(没有提供指令来释放在此方法调用期间分配的本地内存)。本地内存池用于分配在编译时类型或大小未知且程序员不希望在托管堆中分配的对象。由于本地内存池在方法的生存期内不能缩小,语言实现不能使用本地内存池进行通用内存分配。
CLR在哪里分配这个内存池?它是托管堆、线程堆栈吗?
发布于 2013-10-27 15:37:11
这都是有意模糊的,因为它是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寄存器(堆栈指针)中减去0xa 8= 168 = 42x4字节,mov esp,eax指令调整堆栈指针。所以是的,这绝对是从堆栈中得到的。
https://stackoverflow.com/questions/19619768
复制相似问题