2013-05-08 73 views
5

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

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如何确保参考参数在垃圾收集期间不会失效?它们是否像课程参考一样进行调整?

+1

[C#参数引用和.net垃圾回收]的可能重复(http://stackoverflow.com/questions/2500851/c-sharp-parameters-by-reference-and-net-garbage-collection) – 2013-05-08 10:36:15

+0

Eric Lippert对@ rightfold链接问题的回答完美地回答了这个问题。 – 2013-05-08 10:45:04

+0

它们被调整,因为任何方法参数都被认为是一个根,并且所有的根都被调整(它在“CLR via C#”一书中说过) – 2013-05-08 10:49:53

回答

5

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

抖动比此更进一步,它将引用标记为GC_CALL_INTERIOR,指示可能是内部指针的参数的特定情况。您可以通过SSCLI20发行版中的源代码了解GC内部如何处理它。这是不是非常复杂,从gcsmp.cpp片断,GCHeap ::移居()方法:

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源代码以查看该代码。

0

垃圾回收器保留所有指向对象的指针列表。如果没有更多的指向这个对象的指针,它只会处理对象。
在你的情况,你的函数将有一个指向对象(名为“我”),所以GC永远不会处置这个对象。

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

+0

我说的是移动活着的对象,而不是处理死对象。 (另外,'i'不会“指向”一个对象,而是指向一个数据成员。) – fredoverflow 2013-05-08 10:21:57

+0

好吧,你只是在谈论GC的压缩阶段? – Fabske 2013-05-08 11:06:49