6

次のようなものがあるとしましょう:

public class Item
{
    public string Code;
    public List<string> Codes = new List<string>();
}

private void SomeMethod()
{
    List<Item> Items = new List<Item>();
    for (int i = 0; i < 10; i++)
    {
        Item NewItem = new Item();
        NewItem.Code = "Something " + i.ToString();
        NewItem.Codes.Add("Something " + i.ToString());
        Items.Add(Item);
    }

    //Do something with Items
}

後でリスト内のアイテムにアクセスする必要があるため、アイテムをインスタンス化し、解放していません (大まかな例)。

私が疑問に思っているのは、SomeMethod()の実行がいつ終了したかということです。アイテム (およびその内容 - List<> を含む) が逆参照され、ガベージ コレクターが実行時にメモリをクリーンアップできるようになりますか? 基本的に、コードのこのセクションでメモリ リークが発生するか、SomeMethod()処理が終了したときにすべてを参照解除する必要があります。

私の理解では、オブジェクトへの参照を何も保持していない場合、ガベージコレクションが行われるため、このコードは問題ないはずですが、正しく理解していることを確認したかっただけです。

編集:

オブジェクトの 1 つを追加すると、Itemsまだスコープ内にある別のリスト (たとえば、グローバル リスト) に保持されます。何が起こるでしょうか?

4

5 に答える 5

8

変数Itemsがスコープ外になると、ガベージ コレクターは実際にその変数 (およびコードが記述されているため、その内容) を自由に破棄します。

于 2012-12-13T15:56:47.230 に答える
1

Ok、

List<Item> Items

メソッドのスコープで宣言されます。したがって、メソッドが終了すると、スコープ外になり、リストが逆参照されます。

その後、ガベージコレクターが適切であると判断したときに、メモリが解放されます。


余談Itemsですが、は「ローカル」スコープで宣言されているので、私はそれを呼びたいと思いますitems

于 2012-12-13T16:03:32.773 に答える
1

物事を正常に保ち、仕事を続けるために、GC は次の 2 つのことを約束する必要があります。

  1. ごみは回収されます。 これは非常に明白なように思えますが、管理対象オブジェクトをクリーンアップすることを GC が約束しなくても、GC は役に立ちません。

  2. ガベージのみが収集されます。 まだ実行中のオブジェクトを GC がクリーンアップすることを心配する必要はありません。

したがって、いったんItemsスコープ外になると (つまり、関数が戻ると)、コードを実行してもアクセスできなくなるため、何もしなくてもコレクションの対象となります。リスト内の項目にもアクセスできなくなっているため (それらの唯一のリンクがリストにあったため)、それらも資格があります。ただし、リスト内のエントリへの参照を返した場合、そのオブジェクトはまだ有効であり、まだ収集できません。GC は正しいことを行います。

実際、GCはほとんどの場合正しいことを行います。心配しなければならない主なケースは 3 つだけです。

  • コンテナを構築している場合 (独自のListワークライクを作成している場合など)。ユーザーに関する限り、コンテナに「存在」しなくなったオブジェクトは通常、null に設定する必要があります。これにより、GC はそれらをコレクションから到達可能であると認識せず、誤ってそれらを存続させます。たとえば、コレクションから項目を削除する場合は、参照を無効にするか、別の項目で上書きします。
  • 大きな (>~85KB?) オブジェクトの場合。それらは通常、他のすべてを締め出すまでメモリに留まり、その時点で完全な GC サイクルが実行されます。(通常、サイクル中に破棄される可能性が高い特定のオブジェクトのみがチェックされます。完全なコレクションではほとんどすべてがチェックされ、かなり時間がかかりますが、より多くのメモリが解放される可能性があります。)
  • IDisposable オブジェクトまたはネイティブ/アンマネージ リソースを使用している場合。一部の無能な人は、IDisposable を正しく実装する方法を知りません。そのような無能な人によって作成されたライブラリを扱っている場合は、ブロックDispose内でのみ使用するか、ブロック内でのみ使用するようにする必要があります。そうしないとusing、事態が非常に奇妙になります。(.net API のみを使用する場合は、かなり安全ですが、破棄することは依然としてマナーです。)

他のほとんどすべての状況では、GC が機能します。信頼してください。

于 2012-12-13T16:27:45.703 に答える
1

ガベージ コレクターは、コードによって到達できなくなったものをすべて収集します。アイテム リストまたはリスト内に含まれるアイテムのいずれにも到達できなくなるため、ガベージ コレクターはある時点でアイテムを収集します。ガベージ コレクターに関するあなたの理解は正しいです。

于 2012-12-13T15:59:40.470 に答える
1
  1. メソッド内のすべての変数はスタックフレームにあり、これらの変数はすべて、メソッドの実行後にスタックフレームとともに破棄されます。つまり、 SomeMethod() が実行された後、変数 Items は存在しなくなり、新しい List() は「収集可能」とマークされます。

  2. 2番目の質問は、変数Items内のオブジェクトの1つの参照を保持するglobleリスト変数があり、SomeMethod()が実行された後、SomeMethod内のListが「収集可能」としてマークされるということです。グロブルリスト変数によって参照されたアイテムの横にある他のすべてのオブジェクトも「収集可能」としてマークされます。その理由は、リストが実際にヒープ内の正確なオブジェクトを指す参照を保持しているため、共有オブジェクトはできませんglobleList によって参照されるという理由で収集される

于 2012-12-13T16:41:16.090 に答える