変数スコープの最後までオブジェクトは生きているという誤解
先日に引き続き,@IT 会議室突っ込みシリーズ.
未記入さんの書き込み (2008-10-01 21:41) より:
バグではない理由: 参照していると、回収されません。Dispose は、メモリの破棄ではありません。
参照しているというのは fm2 のことでしょうか。fm2 はループ内で宣言されているので、ループ 1周ごとにスコープを抜ける、つまり new Form2() は参照されていない状態になるのではないでしょうか?
GC.Collect() で直前の fm2 が解放されるとは思っていませんが、ループ 1周遅れで、ひとつまえの new Form2() インスタンスは GC で回収されても良さそうに思います。直近の 1インスタンスは GC.Collect() で回収されないと思いますが、それだけでメモリ使用量が増加傾向になるものでしょうか?
よねKENさんのフォローと同じだと思いますが。
オリジナルのコード
while (true) { Form2 fm2 = new Form2(); fm2.ShowDialog(); fm2.Dispose(); GC.Collect(); }GC.Collect が実行されるときには fm2 は参照されています。従って、1つは残ります。
1 つ必ず残るとは限りません.Compact CLR の特定バージョンがそういう実装になっているといった話なら分かりますが,CLI 仕様からは「1 つ必ず残る」と断定はできないはずです.
(C# では) 変数スコープの最後までオブジェクトは生きているというこの誤解,あちこちで目にしますが,実際にはそんなことは保証されていません.C# コンパイラは,スコープ終了点までオブジェクトを延命するようなコードを必要もなく埋め込みません.その結果,デスクトップ CLR では比較的簡単に「スコープ終了前の回収」を見ることができます.特徴的なケースでは,生成したオブジェクトのコンストラクタが完了する前に,そのオブジェクトが回収されることすらあります*1.
詳しくは『 プログラミングMicrosoft .NET Framework 第2版』の第 20 章あたりをどうぞ.
- §20.2 ガベージコレクションのアルゴリズム
- §20.2 ガベージコレクションとデバッグ
- §20.18 その他のガベージコレクタのパフォーマンス上の注意点
プログラミングMicrosoft .NET Framework 第2版 (マイクロソフト公式解説書)
- 作者: ジェフリーリッチャー,Jeffrey Richter,吉松史彰
- 出版社/メーカー: 日経BPソフトプレス
- 発売日: 2006/12
- メディア: 単行本
- 購入: 6人 クリック: 148回
- この商品を含むブログ (51件) を見る