本文主要是一种验证,对与fixed关键字操作的的验证,希望通过本文能让大家对fixed关键字理解得更深入一些。同时也会分析程序员可能出现问题的一些坏习惯,希望对大家有所帮助。
#T#
之前谈到String连接操作的性能,其中会涉及到unsafe操作,而unsafe操作必然会涉及到指针,于是fixed关键字也应运而生。fixed关键字是用来pin住一个引用地址的,因为我们知道CLR的垃圾收集器会改变某些对象的地址,因此在改变地址之后指向那些对象的引用就要随之改变。这种改变是对于程序员来说是无意识的,因此在指针操作中是不允许的。否则,我们之前已经保留下的地址,在GC后就无法找到我们所需要的对象。现在就来我们就来做一个小实验,验证fixed关键字的效果。
当然,这个实验很简单,简单地可能会让您笑话。首先我们来准备一个SomeClass类:
- public class SomeClass
- {
- public int Field;
- }
然后准备一段代码:
- private static unsafe void GCOutOfFixedBlock()
- {
- var a = new int[100];
- var c = new SomeClass();
- fixed (int* ptr = &c.Field)
- {
- PrintAddress("Before GC", (int)ptr);
- }
- GC.Collect(2);
- fixed (int* ptr = &c.Field)
- {
- PrintAddress("After GC", (int)ptr);
- }
- }
- private static void PrintAddress(string name, int address)
- {
- Console.Write(name + ": 0x");
- Console.WriteLine(address.ToString("X"));
- }
在GCOutOfFixedBlock方法中,我们首先分配一个长度为100的int数组,然后新建一个SomeClass对象。新建数组的目的在于制造“垃圾”,目的是在调用GC.Collect方法时改变SomeClass对象在堆中的位置。由于垃圾回收发生在fixed代码块之外,这样我们前后两次打印出的值便是不同的:
Before GC: 0x1A058C0
After GC: 0x1975DF4
值得注意的是,这段代码必须在Release模式下进行编译,让CLR执行代码时进行优化,这样CLR便会在垃圾回收时发现a数组已经是垃圾了(因为后面的代码不会用它),于是会将其回收——否则便无法看出地址改变的效果来。那么,我们重写一段代码:
- private static unsafe void GCInsideFixedBlock()
- {
- var a = new int[100];
- var c = new SomeClass();
- fixed (int* ptr = &c.Field)
- {
- PrintAddress("Before GC", (int)ptr);
- GC.Collect(2);
- }
- fixed (int* ptr = &c.Field)
- {
- PrintAddress("After GC", (int)ptr);
- }
- }
结果如下:
Before GC: 0x1B558C0
After GC: 0x1B558C0
由于GC发生在fixed代码块内部,因此c对象被pin在堆上了,于是GC前后c对象的地址没变,这就是fixed的作用。那么,下面这段代码运行结果是什么呢?
- private static unsafe void Mixed()
- {
- var a = new int[100];
- var c1 = new SomeClass();
- var c2 = new SomeClass();
- fixed (int* ptr1 = &c1.Field)
- {
- PrintAddress("Before GC", (int)ptr1);
- }
- fixed (int* ptr2 = &c2.Field)
- {
- PrintAddress("Before GC (fixed)", (int)ptr2);
- GC.Collect(2);
- }
- fixed (int* ptr1 = &c1.Field)
- {
- PrintAddress("After GC", (int)ptr1);
- }
- fixed (int* ptr2 = &c2.Field)
- {
- PrintAddress("After GC (fixed)", (int)ptr2);
- }
- }
至于为什么是这个结果,那便和CLR实现方式有关了。
原文标题:验证fixed关键字效果的小实验
链接:http://www.cnblogs.com/JeffreyZhao/archive/2009/11/29/lab-fixed-keyword.html