0

スコープから外れたときに.NETのオブジェクトがどうなるか知りたいです。このようなもの:

class A
{
    ClassB myObjectB = new ClassB();
}
//what happens to object at this point here?

記憶の中で何が起こりますか?GCがスコープから外れ、ヒープ内の参照を失うと、GCが呼び出されますか?

4

5 に答える 5

3

メモリ内で何が起こるか? GC が範囲外になったときに呼び出され、ヒープ内で参照が失われますか?

いいえ - この時点では GC は呼び出されません。

何が起こるかというと、オブジェクトはメモリに残されますが、「ルート化されていない」状態になります。基本的に、他のオブジェクトからそのオブジェクトへの参照はありません。そのため、オブジェクトはガベージ コレクションの対象になりました。

将来のある時点で、GC が実行されます。これが発生すると、ルート化されていないオブジェクトがガベージ コレクションの対象になります。オブジェクトを保持する世代に応じて、その時点でクリーンアップされる場合とされない場合があります。最終的に、プログラムの実行が継続され、メモリ不足により適切な世代が収集されると、そのオブジェクトのメモリが再利用されます。

これが発生する明確な時点はありません (明示的に を呼び出さない限りGC.Collect、これは悪い考えです)。ただし、マネージ コードを使用すると、これがいつ発生するかについて心配する必要はありません。特定のアプリケーションに適したときに、適切な場合に発生すると想定してください。

于 2012-05-02T23:19:11.697 に答える
3

pst のコメントに続いて、より良い例は次のようになります。

void M() 
{ 
    ClassB myObjectB = new ClassB(); 
} 
//what happens to object at this point here? 

この例でmyObjectBは、 はフィールドではなくローカル変数です。では、ローカル変数がスコープ外になるとどうなるでしょうか? 何もない!スコープは、C# のオブジェクトの有効期間とは関係ありません。

実際に起こることは、JIT コンパイラーがある時点でオブジェクトを解放することを決定することです。変数がメソッドの残りの部分で使用されない場合は、変数のスコープが終了する前にする ことができます。オブジェクトが参照されなくなると、他の回答でも言及されているように、GC によるコレクションの対象になります。GC が実行されるまで (実際には、GC がオブジェクトが存在する世代を収集するまで)、実際には収集されません。

pst が暗示しているように、フィールドは含まれているオブジェクトに到達可能な場合は常に到達可能であるため、フィールドは貧弱な例です。そのため、スコープとオブジェクトの有効期間の分離はさらに大きくなります。

class A
{
    private object o = //whatever
}

void B()
{
    var a = new A();
    // here, the field o is not in scope, but the object it refers to is reachable and cannot be collected.
    GC.KeepAlive(a);
}
于 2012-05-02T23:22:30.250 に答える
2

「スコープから外れる」ことは、より C++ 固有の考え方であることがわかります。特定のスコープの終わりに、自動ストレージを持つオブジェクトが解放され、そのデストラクタが呼び出されます。

C# の世界では、「範囲外」ということはありません。変数 (読み: 名前) は特定のスコープに存在し、それだけです。GC はこれをまったく気にしません。オブジェクトは、その名前のスコープが終了する前に収集することも、それを参照するものと GC がコレクションが必要であると判断する時期に応じて、かなり後になって収集することもできます。

次に、2 つの概念を分離して、別々に推論する必要があります。スコーピングはすべて名前に関するものですが、ガベージ コレクションはオブジェクトの到達可能性のみを考慮します。既知のルートのいずれかからオブジェクトに到達できなくなった場合、そのオブジェクトは収集のためにスケジュールされます。

于 2012-05-02T23:20:08.627 に答える
1

一般的に言えば、ガベージ コレクションは 3 つの異なる世代 (0、1、または 2) で発生します。これらのそれぞれがいつ収集されるかは、OS が必要とするリソースの量によって異なります。

GC.Collect() を呼び出すと、利用可能なすべてのリソースが収集されますが、収集するリソースの世代を定義することができます。

于 2012-05-02T23:33:49.590 に答える
1

オブジェクトを参照するものがない場合、最終的に GC によって収集されます。問題は、それがいつ起こるかを正確に予測することはできないということです。あなたはただ知っています、それは起こります。

于 2012-05-02T23:12:25.620 に答える