如果我通过引用函数传递数据成员会发生什么情况,并且在该函数运行时,垃圾收集器开始运行并将包含数据成员的对象移动到内存中?
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如何确保引用参数在垃圾收集期间不会失效?它们是否像课程参考一样进行调整?
答案 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。