C#中的安全指针

http://topic.csdn.net/t/20051005/15/4308139.html


我们都知道,CLR保存程序中的数据,程序员可以控制的有两个地方:保存引用对象实例的堆和保存值类型和对象引用的堆栈。如下面的代码

public   void   MethodA()
{
        int   intValue   =   123;   //   在堆栈中建立了一个Int32类型变量

        System.Text.StringBuilder   sb   =   new   StringBuilder();   //   建立了一个类实例引用

        System.Text.StringBuilder   sb2   =   sb;   //   建立第二个类引用,指向第一个类实例
}

从上面能够看出,在代码中建立了三个变量,一个是Int32整数类型变量,两个是StringBuilder类实例引用变量,他们同时指向保存在CLI堆中的同一个堆实例。

我们能发现,当这个名为“MethodA”的方法执行完毕后,这三个变量本身,还有他们指向的数据本身都将被抛弃,如果这个方法有返回值,那么,这个值所引用的数据将被保留。

所以我怀疑,指向CLR堆中类型实例的引用,它在.Net内部可能也是一种类型,有可能是一个struct(结构),因为结构是值类型,所以可以存放在速度快的堆栈中,因为它是一种结构,对象引用变量有与值类型变量同样的特性,在方法内部定义的引用除非方法返回值返回,否则方法执行结束后自动销毁,在方法的不同区块中定义的对象引用不能运行在区块外面,这明显是堆栈的后进先出特性。如
public   void   MethodB()
{
        int   i   =   123;
        try
        {
                StringBuilder   sb   =   new   StringBuilder();
        }
        finally
        {
                //   ...
        }
        i   =   456;   //   这时,重新使用i变量可以的
        sb.Append( "... ");   //   在这里使用try块中的定义变量就不行
}

所以我觉得对象引用实际上在CLR中被表示成一个自动指针一样的东西,他是一个结构,而这个结构具体保存了哪些数据微软没有公布,不过至少有几点,首先是指向对象实例入口地址的指针,这是肯定的,还有就是.Net中有GC,为了保证GC执行,.Net中保存在CLR堆中的所有对象实例数据里面都有一个固定大小的对象头,里面包含了一些信息,如对象引用,对象执行接口表之类。这个对象头的入口地址肯定也在这个对象引用里面。另外就是当前对象引用的实例具体在内存中的大小,多少字节等。

有了这些东西,实际上我们操作对象引用,如方法返回值,方法参数对象等,不过就是类似于
int   i   =   123;
int   j   =   i;
这样的赋值操作,当前上面我写的是Int32类型,引用类型也同样。

另外,我怀疑GC在执行垃圾收集的时候,就是扫描所有堆栈内的这些引用对象的结构,然后再用一些算法去除指向同一个对象实例的结构,那么剩下来的结构的个数就是CLR堆内对象实例的个数,然后剩下来的对象实例就是没有被引用的对象实例,自然就可以安全的被删除了。

原文地址:https://www.cnblogs.com/Eleanore/p/2518122.html