2013-05-08 74 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