2013-05-08 16 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; 
    } 
} 

ガベージコレクション中に参照パラメータが無効にならないようにするにはどうすればよいですか?彼らはクラス参照のように調整されていますか?

+1

[C#パラメータの参照と.netガベージコレクション]の可能な複製(http://stackoverflow.com/questions/2500851/c-sharp-parameters-by-reference-and-net-garbage-collection) –

+0

Eric @ rightfoldのリンクされた質問に対するLippertの答えはこれを完全に答えている。 –

+0

メソッドパラメータがルートとみなされ、すべてのルーツが調整されるため、調整されます(「C#を使用したCLR」を参照してください) –

答えて

5

まあ、ガベージコレクタにとっては人生は簡単ではありません。しかし、このような内部ポインタに対処する方法を知っています。 C#やVB.NETのような管理された言語からは隠されていますが、C++では内部のポインタが言語構文によって簡単に生成されることがあります。 C++ PrimerのStan Lippmanはblog postを持っており、interior_ptrキーワードの主な動機をC++/CLIで利用できます。

ジッタはこれを超えて一歩進んで、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

ガベージコレクタは、オブジェクトへのすべてのポインタのリストを保持します。このオブジェクトへのポインタがそれ以上存在しない場合にのみ、オブジェクトを破棄します。
あなたの関数にはオブジェクト( "i"という名前)へのポインタがあり、GCはこのオブジェクトを決して処理しません。

GCがどのように機能するかについての詳細な記事を読むことができますhere

+0

私は死んだオブジェクトを処分しないで、生きているオブジェクトを動かすことについて話しています。 (また、 'i'はオブジェクトを指しているのではなく、データメンバに向いています。) – fredoverflow

+0

これで、GCの圧縮段階について話していますか? – Fabske

関連する問題