通过引用传递数据成员

fre*_*low 5 c# clr garbage-collection 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

在垃圾收集过程中,CLR如何确保引用参数不会失效?他们是否像课程参考一样调整?

Han*_*ant 5

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

抖动比这更进一步,它将引用标记为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;
   }
Run Code Online (Sandbox Code Playgroud)

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