BT

.NETのメモリリークに対処する

| 作者: Abel Avram フォローする 10 人のフォロワー , 翻訳者 徳武 聡 フォローする 0 人のフォロワー 投稿日 2009年11月8日. 推定読書時間: 3 分 |

原文(投稿日:2009/11/05)へのリンク

ソフトウエアアーキテクトでありコンサルタントでもあるFabrice Marguerie氏がMSDNに記事を書いた。内容は>NETアプリケーションでのリソースとメモリリークの検出方法と防止策についてだ。この記事には、.NETアプリケーションの実装をする過程でどのようにしてメモリやリソースのリークが発生し、どうすれば防げるのかについて説明してある。

C#のような言語は、プログラムがメモリへの参照を完全に失ったとき、ガベージコレクタがメモリ上の後処理を行ってくれるので、本来はメモリリークは発生しない。Fabrice Marguerie氏によるとメモリリークが発生するのは、あるメモリ領域がもう必要なくなったにも関わらず、そのプログラムの一カ所からだけでも参照されている場合だ。この場合、このメモリ領域が到達不可能ならガベージコレクタは再度、解放を行おうとする。しかし、プログラムから参照されているが使われてはいないメモリ領域がある限り、その領域はリークしていることになる。

Fabrice氏は同じようなリークの対象になるOSのリソースを一覧している。

  • システムはウィンドウを管理するためにユーザオブジェクトを使っています。ユーザオブジェクトの中に含まれるのは、アクセラレータテーブル、キャレット、カーソル、フック、アイコン、そしてメニューとウィンドウです。
  • GDIオブジェクトはグラフィックをサポートします。つまり、ビットマップやブラシ、デバイスコンテキスト(DC)、フォント、メモリDC、メタファイル、パレット、ペンや描画領域等です。
  • カーネルオブジェクトがサポートするのはメモリ管理、プロセスの実行、プロセス間通信(IPC)です。つまり、ファイルやプロセス、スレッド、セマフォ、タイマーやアクセストークン、ソケット等を扱います。

これらのリソースには限りがある。リジストリキーGDIProcessHandleQuotaとUSERProcessHandleQuotaにはひとつのプロセスが利用できる最大のGDIオブジェクトとユーザオブジェクトの数が設定されている。デフォルトの値は 10,000だ。ほとんどのアプリケーションではこの値で十分だが、これらのリソースをあまりにも多く使ってしまうとシステムは別種の限界に達してしまう。その限界とは、ひとつのWindowsのセッションのハンドル数が65,536までということだ。しかし、65,536は理論値であり、Fabrice氏の報告よると実際は11,000くらいが上限になる。氏は、システムリソースは注意深く扱う必要があり不必要になったら解放するべきだ、と結論づけている。

氏はどのようにリークが発生するか説明するため、リークの根本原因を一覧している。

  • 静的な参照を使っている
  • 購読されていないイベント–氏の考えではこれがリークの原因としては最も一般的だ。
  • 購読されていない静的なイベント
  • Disposeメソッドを呼んでいない
  • 不完全なDisposeメソッドを使っている
  • WindowsフォームでBindingSourceコンポーネントを使い間違えている
  • WorkItem/CABを使うときにRemoveメソッドを呼んでいない

氏の記事にはリークを防ぐための方法についてもアドバイスしている。

  • オブジェクトの利用者ではなく、作成者か所有者がオブジェクトの破棄に対して責任を持つこと。
  • 不必要なイベントは常に購読しないこと。これはDisposeメソッド内で安全にできます。
  • オブジェクトがイベントを生成しなくなったら、イベントのリスナをすべて削除するためにそのオブジェクトにnullを設定すること。
  • モデルやビューであるオブジェクトの参照をつかう場合、 ビュー に渡すのはそのオブジェクトのクローンするのがいいでしょう。こうすることで、誰がどのオブジェクトを使っているのか見失わなくなります。
  • システムリソースを使うときはusingブロックで囲むことで、ブロックを抜けたときに自動的にDisposeメソッドが呼ばれるようにすること。

Fabrice氏は最後に、オブジェクトやリークを扱うのを支援してくれる次のようなツールを紹介している。GDILeaks (リンク先はEXEファイル)、dotTrace.NETメモリプロファイラSOS.dll、そして WinDbg

この記事に星をつける

おすすめ度
スタイル

こんにちは

コメントするには InfoQアカウントの登録 または が必要です。InfoQ に登録するとさまざまなことができます。

アカウント登録をしてInfoQをお楽しみください。

あなたの意見をお聞かせください。

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

このスレッドのメッセージについてEmailでリプライする
コミュニティコメント

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

このスレッドのメッセージについてEmailでリプライする

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

このスレッドのメッセージについてEmailでリプライする

ディスカッション

InfoQにログインし新機能を利用する


パスワードを忘れた方はこちらへ

Follow

お気に入りのトピックや著者をフォローする

業界やサイト内で一番重要な見出しを閲覧する

Like

より多いシグナル、より少ないノイズ

お気に入りのトピックと著者を選択して自分のフィードを作る

Notifications

最新情報をすぐ手に入れるようにしよう

通知設定をして、お気に入りコンテンツを見逃さないようにしよう!

BT