通过引用传递数据成员

时间:2013-05-08 10:12:49

标签: c# garbage-collection clr pass-by-reference

如果我通过引用函数传递数据成员会发生什么情况,并且在该函数运行时,垃圾收集器开始运行并将包含数据成员的对象移动到内存中?

class SomeClass
{
    int someDataMember;

    void someMethod()
    {
        SomeClass.someFunction(ref someDataMember);
    }

    static void someFunction(ref int i)
    {
        i = 42;

        int[] dummy = new int[1234567890];
        // suppose the Garbage Collector kicks in here

        i = 97;
    }
}

CLR如何确保引用参数在垃圾收集期间不会失效?它们是否像课程参考一样进行调整?

2 个答案:

答案 0 :(得分:5)

好吧,垃圾收集者的生活并不容易。但它知道如何处理这样的内部指针。很好地隐藏在C#和VB.NET等托管语言中,它在C ++中可见,其中内部指针可以通过语言语法轻松生成。 C ++ Primer成名的Stan Lippman对它们有一个blog post,给出了C ++ / CLI中可用的interior_ptr关键字的一些主要动机。

抖动比这更进一步,它将引用标记为GC_CALL_INTERIOR,指示可能是内部指针的参数的特定情况。您可以使用SSCLI20发行版中提供的源代码查看GC内部的处理方式。它不是非常复杂,来自gcsmp.cpp,GCHeap :: Relocate()方法的片段:

   if (flags & GC_CALL_INTERIOR)
   {
       if ((o < gc_heap::gc_low) || (o >= gc_heap::gc_high))
       {
           return;
       }
       o = gc_heap::find_object (o, gc_heap::gc_low);

       offset = (BYTE*)object - o;
   }

因此,简而言之,通过检查指向GC堆段下限/上限的指针,发现它不能是引用引用类型对象成员的指针,这是一个非常快速的测试。然后进行一些挖掘,将内部指针映射到包含该成员的对象。查看SSCLI20源代码以查看该代码。

答案 1 :(得分:0)

垃圾收集器保留指向对象的所有指针的列表。如果没有更多指向此对象的指针,它只会处置对象 在您的情况下,您的函数将有一个指向对象的指针(名为“i”),因此GC将永远不会处置此对象。

您可以阅读有关GC如何运作的完整文章here

相关问题