打自己脸——有关.net对象分配
之前发过的那篇.NET的GC机制和GC知识学习里面有一选项为:
A. 值类型的对象会被分配到Stack上,而引用类型的对象会被分配到Large Object Heap上。
今天在写前一篇Blog时候,发现这句话其实大错特错,虽然这个选项本身就是故意加入了错误,作为选择题答案出现,但此错非彼错。还好题目没有正式使用,不然会被人打脸打得啪啪响。在尚未被人打脸之前还是先自打比较好。先看前半句:
值类型的对象会被分配到Stack上
拿值类型中最常被提到用来和引用类型相比较的Struct来说,它一定分配到Stack上吗?当然不是。这一点题目已经涉及到了,就是大于85k的对象会分配到LOH上。但忽略的一点是一般尺寸的值类型对象也有可能分配到Heap上:
- 类成员变量,就算是值类型也是在Heap上分配;
- 局部值类型变量,涉及到和闭包相关的特性时。
第一条就不说了。第二条例如下面这个例子,i和j都是局部值类型变量,他们都在Stack上吗?
private void Form1_Load( object sender, EventArgs e ) {
int j = 0;
int i = 0;
Func foo = () => {
return i;
};
}
.method private hidebysig instance void Form1_Load(object sender,
class [mscorlib]System.EventArgs e) cil managed
{
// 代码大小 31 (0x1f)
.maxstack 3
.locals init ([0] int32 j,
[1] class [System.Core]System.Func`1 foo,
[2] class WindowsFormsApplication1.Form1/'<>c__DisplayClass3' 'CS$<>8__locals4')
IL_0000: newobj instance void WindowsFormsApplication1.Form1/'<>c__DisplayClass3'::.ctor()
IL_0005: stloc.2
IL_0006: nop
IL_0007: ldc.i4.0
IL_0008: stloc.0
IL_0009: ldloc.2
IL_000a: ldc.i4.0
IL_000b: stfld int32 WindowsFormsApplication1.Form1/'<>c__DisplayClass3'::i
IL_0010: ldloc.2
IL_0011: ldftn instance int32 WindowsFormsApplication1.Form1/'<>c__DisplayClass3'::'
b__2'()
IL_0017: newobj instance void class [System.Core]System.Func`1::.ctor(object,
native int)
IL_001c: stloc.1
IL_001d: nop
IL_001e: ret
} // end of method Form1::Form1_Load
另外漏了一点,在更正:值类型并不总是分配在栈上一文中提到,还有一种会被分配到Heap上的值类型:
- 数组内的值类型对象,会被一同分配到Heap上。