3

IDisposable を継承するオブジェクトへのポインターを含むクラスがあります。

class Foo 
{
    private Bar bar;

    private test() 
    {
        bar = CreateBarFactory();
    }

};

bar は、test() で設定されている場合を超えて使用されることはありません。

Foo インスタンスがまだ存在していても、GC が bar を破棄することを許可されているかどうか疑問に思っていますか?

もしそうなら、これを防ぐ方法はありますか?bar は、ref カウントを含むオブジェクトへのポインターです。Disposed() の場合、ref が解放され、一部の機能が無効になります。

4

3 に答える 3

4

foo のインスタンスがまだ存在している場合 (つまり、誰かがそれへの参照を保持している.. それを維持している場合)、bar は収集されません。使用中の GC によって「到達可能」として扱われます。

到達可能なオブジェクトのメンバーも到達可能であると見なされます。

于 2012-12-02T06:54:35.530 に答える
2

用語を混同しないでください。C#にはポインターがありますが、それはあなたが持っているものではありません。参照があります。重要なことに、参照ガベージコレクターに影響を与えますが、ポインター自体は影響を与えません。(*)

のインスタンスFooが到達可能である限り、への参照barはそのオブジェクトも到達可能に保ちます。ファイナライザーがある場合FooBarファイナライザーでFooは、何も想定してはいけない状況が1つありますbar。これは、すでにファイナライズされている可能性があります。

ご指摘のとおり、アクセスする他のメソッドは呼び出されbarませんが、GCとJITはこの種の分析を実行しません。オブジェクト参照の場合、オブジェクト全体が到達可能であると見なされ、オブジェクトに含まれるすべての参照が追跡され、同様に配置されたオブジェクトが到達可能としてマークされます。これは、オブジェクトへのリフレクションベースのアクセスが無効な参照を取得しないようにするために行う必要があります。これは、オブジェクトが、使用しなくなる大きなヘルパーオブジェクトを割り当てた場合に、(この限られた状況で)参照をに設定すると便利な場合がある理由でもありますnull

将来のコードが実行されるかどうかを考慮する唯一のライフタイム分析、ローカル変数に関して、単一のメソッド本体内のコードです。メソッド内のローカル参照変数は、その変数へのそれ以上の参照が発生しない場合、オブジェクトを存続させるのに十分ではありません。これは、JITとGCの間で共同で解決されます。


(*)人々は、ポインタがオブジェクトを存続させると考えることがあります。これは厳密には真実ではありません。ポインターを生成できるピン留めの動作は、オブジェクトを存続させますが、オブジェクトがピン留めされた時間を超えてポインターを保持することを妨げるものは何もありません。もちろん、そのようなときにポインタを参照解除することは安全ではありません...


そして、別の用語の問題:

GCがバーを処分することを許可されているかどうか疑問に思います

GCは何も処理しません。廃棄は、オブジェクトがIDisposableを実装し、オブジェクトのユーザーがDispose(直接またはusingブロックなどを介して)それを呼び出すときに発生します。

GCはを呼び出しませんDispose。ファイナライザーがオブジェクトに定義されている場合(したがって、上記の警告が適用される場合)、ファイナライザーを呼び出して、オブジェクトを収集する場合があります

于 2012-12-02T07:34:04.663 に答える
0

このクラスを正しく機能させるには、IDisposableiterfaceから継承しDispose()、を呼び出すメソッドを実現する必要がありますbar.Dispose()。この拡張リソースは、GCが収集を決定したときではなく、解放できるときに正確に解放されることを保証します。

于 2012-12-02T08:36:04.027 に答える