トップ 差分 一覧 ソース 検索 ヘルプ PDF RSS ログイン

ガベージコレクション、マネージリソース、アンマネージリソース、Dispose、Finalize

[カテゴリ:言語]
[カテゴリ:.NET]
[カテゴリ:C#]

ガベージコレクション(GC)とは?

  • 誰からも参照されなくなったオブジェクトを自動的に回収し解放する機能
  • これによりプログラマが明示的にメモリの確保・解放を行う必要がなくなる。
    • 解放忘れや、2重解放を回避できる。
  • とはいっても万能ではない。

Microsoft .NET Framework のガベージコレクション
http://uchukamen.com/Programming/GC/

完全にGCを行うソースコード

System.GC.Collect(); // アクセス不可能なオブジェクトを除去
System.GC.WaitForPendingFinalizers(); // ファイナライゼーションが終わるまでスレッド待機
System.GC.Collect(); // ファイナライズされたばかりのオブジェクトに関連するメモリを開放

.NET アプリケーションのパフォーマンスとスケーラビリティの向上 - 第 5 章 「マネージ コ ード パフォーマンスの向上」
http://msdn.microsoft.com/ja-jp/library/ms998547.aspx#scalenetchapt05_topic10

マネージリソースとアンマネージリソース

  • マネージリソースとは?
    • GCの管理下に*ある*リソース
  • アンマネージリソースとは?
    • GCの管理下に*ない*リソース
    • ファイルハンドル、ウィンドウハンドル(HWND)、データベース接続 など。

マネージリソースのライフサイクル

オブジェクトが生成される(メモリ確保)
↓
↓プログラム中でオブジェクトを利用する。
↓
:
↓
↓GCが利用を終了したオブジェクトと判断する。
↓
オブジェクトが破棄される(メモリ解放)

アンマネージリソースのライフサイクル

アンマネージリソースはGCの管理下に置けない為、プログラム中でライフサイクルを記述する必要がある。

  • プログラマは意識して Dispose を Call しアンマネージリソースを解放しなければならない。(明示的な解放)
  • もし、Dispose の Call を忘れていたら?
    • GCにより Finalize が Call されアンマネージリソースが解放される。(暗黙的な解放)
オブジェクト生成
↓
↓プログラム中でオブジェクトを利用する。
↓
↓プログラム中で this.Dispose() を Callする。(明示的にアンマネージリソース解放)
↓
:
↓
↓GCが利用を終了したオブジェクトと判断する。
↓
:
↓
↓GCが this.Finalize() を Callする。(暗黙的にアンマネージリソース解放)
↓
オブジェクト破棄

追加知識

  • Finalizeは、C#においてはデストラクタ(~ClassName)と等価
  • プログラマがDisposeして、GCがFinalizeするのは無駄では?
    • 一般的に、Disposeしたときには、Finalizeは実行されない。
      • Disposeの実装で、DisposeGC.SuppressFinalize() を Call することで、GCに対して Finalize キャンセルを指示できる。
  • 実装によっては Close が Dispose と等価であったりするらしい。

アンマネージ リソースをクリーンアップするための Finalize および Dispose の実装
http://msdn.microsoft.com/ja-jp/library/b1yfkh5e.aspx

Object.Finalize メソッド (System)
http://msdn.microsoft.com/ja-jp/library/system.object.finalize(VS.80).aspx

自前クラスでの Dispose と Finalize をどう扱うか?

  • 自前クラスでDisposeを持つクラスを利用する場合、確実にDisposeをCallすることを考える。
    • usingを積極的に利用する。
    • メンバ変数に「Disposeを持つクラス」を使ったときは、自前クラスにもDisposeを実装し、ここで メンバ変数.Dispose() をCallする。
  • アンマネージリソースを扱うクラスを設計するとき、確実にリソースを解放する為、DisposeとFinalizeはセットで考える必要がある。

マネージリソースのみならDisposeは不要?

そうなのだけど・・・

  • 循環参照していたとき、.NetのGCは検出してくれるんだっけかな?
    • 検出してくれる。
  • 積極的にリソースを解放することを意識するなら(GCの解放を助ける・促すという意味において)自前クラスにおいてDisposeは実装した方がよさそうな気もする。
      • 特にたくさんのマネージリソースを持つ場合とか?

どうなんだろう?

Disposeはどう書くべき? - Insider.NET
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=45412&forum=7

Dispose メソッドの実装
http://msdn.microsoft.com/ja-jp/library/fs2xkftw.aspx

最終更新時間:2009年02月12日 03時52分05秒