每个线程对应一个stack,线程创建的时候CLR为其创建这个stack,stack主要作用是记录函数的执行情况。值类型变量(函数的参数、局部变量等非成员变量)都分配在stack中,引用类型的对象分配在heap中,在stack中保存heap对象的引用指针。GC只负责heap对象的释放,heap内存空间管理
Heap内存分配

除去pinned object等影响,heap中的内存分配很简单,一个指针记录heap中分配的起始地址,根据对象大小连续的分配内存
Stack结构
每个函数调用时,逻辑上在thread stack中会产生一个帧(stack frame),函数返回时对应的stack frame被释放掉
用个简单的函数查看执行时CLR对栈的处理情况:
{
int r = Sum(2, 3, 4, 5, 6);
}
private static int Sum(int a, int b, int c, int d, int e)
{
return a + b + c + d + e;
}
push 4 ;第3个参数到最后一个参数压栈
push 5
push 6
mov edx,3 ;第1、第2个参数分别放入ecx、edx寄存器
mov ecx,2
call dword ptr ds:[00AD96B8h] ;调用函数Sum,执行call的时候返回地址(即下面这条mov语句的地址)自动压栈了
mov dword ptr [ebp-0Ch],eax ;将函数返回值设置到局部变量r中(函数调用结束返回值在eax寄存器中)
;====函数Sum====
push ebp ;保存原始ebp寄存器
mov ebp,esp ;将当前栈指针保存在ebp中,后面使用ebp对参数和局部变量寻址
sub esp,8 ;分配两个局部变量
mov dword ptr [ebp-4],ecx ;第1个参数放入局部变量
mov