VisualBasic2012(VB.NET)でビルドするデスクトップアプリケーションの効率的なメモリリークの調べ方についてアドバイスを下さい

参考になりそうな本でも構いません

My.Application.Info.WorkingSetとdebug.writelineをいたるところに配置することで、大体の発生箇所についてめどが立ったこともないのですが、そこから先の原因箇所へ絞り込むことができません

とりあえずdisposeが使えるものはできるだけusingで括ってみたり、画像とかファイルアクセスのところは気をつけたりしているつもりなんですが、一向にメモリ消費ペースが変わらず、さじを投げています

よろしくお願いします

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2013/06/05 01:55:03
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:Oyama1102 No.3

回答回数3ベストアンサー獲得回数1

ポイント100pt

メモリリークの原因調査のアプローチをいくつか書きます。

1.再現性を確認する。

  特定の手順、特定の操作で再現するのであれば、
  ある程度、原因個所が絞り込めていることになります。

  次その部分を切り出した小さいプログラムを作って、
  再現性があるか確認します。

  これを繰り返すと、原因個所が狭めることが出来きます。
  面倒であれば、プログラムをばっさり消してみて、
  再現するか確認するもの手です。

  また、プログラムを半分に分けて、
  どっちで再現するかを繰り返すのも有効と思います。

2.画像やファイルのデータを静的変数に保持していないかを確認する。
  クラス変数であっても、そのクラスのインスタンス自体を、
  静的変数に保持していないかを確認する。

  通常の変数はどこからも利用されなくなると、ガベージコレクション(GC)の
  回収対象になって、そのうちGCが破棄してくれますが、静的変数は、
  大量データを格納しない等、メモリ管理に気をつける必要があります。

3.ループ処理の中で、ListにデータをAddしている箇所を確認する。
  Listが静的変数だったりすると、Deleteしない限りは増え続けます。

4.各種のプロファイラを使ってみる。

  http://d.hatena.ne.jp/Wacky/20080823/1219500273

id:halohalolin

Oyama1102さんありがとうございます

1.フォーム処理などが絡んで分離が難しいので、My.Application.Info.WorkingSetとdebug.writelineをいたるところに配置する方法を取っていたのですが、検討します

2.ListViewでサムネイルを一覧表示している(そしてリストは操作やタイマー処理で書き換わる)プログラムなので、怪しいと考えています
改めて確認してみます

3.ジェネリックのList早い!もうArray.Resizeとか使えない!
と、調子に乗ってあちこちで使いまくっていたので確認してみます

4.参考にさせていただきます

2013/05/31 16:22:27
id:halohalolin

4番ですが

EQATEC Profiler
http://www.eqatec.com/tools/profiler

が良さげですね、また試してみます!

2013/05/31 16:34:26

その他の回答4件)

id:todo36 No.1

回答回数34ベストアンサー獲得回数5

id:halohalolin

todo36さんありがとうございます。
CLR プロファイラはよくわからなくて挫折していたのですが、検討させていただきます。

2013/05/31 16:11:25
id:SweetSmile1978 No.2

回答回数199ベストアンサー獲得回数31

ポイント100pt

実際にメモリリークしているのでしょうか?
.NET はガベージコレクタがあるので
ファイルやネットワーク、データベースアクセスなど
一部で dispose する以外は意図的なメモリ解放は必要ないはずです。

ただ、実際にメモリがいつ解放されるかは保障されていません。
必要でなくなった時点ですぐに開放したいということでしょうか?

id:halohalolin

SweetSmile1978さんありがとうございます。

タイマーで定期的にとある処理をするWindowsフォームプログラムを作っています。
そのとある処理が行われるたびにメモリーは多少増減するものの、全体的には増加傾向となっている(最初のころに戻ることはない)ので、メモリーリークの疑いが濃厚だと考えています。

2013/05/31 16:14:44
id:Oyama1102 No.3

回答回数3ベストアンサー獲得回数1ここでベストアンサー

ポイント100pt

メモリリークの原因調査のアプローチをいくつか書きます。

1.再現性を確認する。

  特定の手順、特定の操作で再現するのであれば、
  ある程度、原因個所が絞り込めていることになります。

  次その部分を切り出した小さいプログラムを作って、
  再現性があるか確認します。

  これを繰り返すと、原因個所が狭めることが出来きます。
  面倒であれば、プログラムをばっさり消してみて、
  再現するか確認するもの手です。

  また、プログラムを半分に分けて、
  どっちで再現するかを繰り返すのも有効と思います。

2.画像やファイルのデータを静的変数に保持していないかを確認する。
  クラス変数であっても、そのクラスのインスタンス自体を、
  静的変数に保持していないかを確認する。

  通常の変数はどこからも利用されなくなると、ガベージコレクション(GC)の
  回収対象になって、そのうちGCが破棄してくれますが、静的変数は、
  大量データを格納しない等、メモリ管理に気をつける必要があります。

3.ループ処理の中で、ListにデータをAddしている箇所を確認する。
  Listが静的変数だったりすると、Deleteしない限りは増え続けます。

4.各種のプロファイラを使ってみる。

  http://d.hatena.ne.jp/Wacky/20080823/1219500273

id:halohalolin

Oyama1102さんありがとうございます

1.フォーム処理などが絡んで分離が難しいので、My.Application.Info.WorkingSetとdebug.writelineをいたるところに配置する方法を取っていたのですが、検討します

2.ListViewでサムネイルを一覧表示している(そしてリストは操作やタイマー処理で書き換わる)プログラムなので、怪しいと考えています
改めて確認してみます

3.ジェネリックのList早い!もうArray.Resizeとか使えない!
と、調子に乗ってあちこちで使いまくっていたので確認してみます

4.参考にさせていただきます

2013/05/31 16:22:27
id:halohalolin

4番ですが

EQATEC Profiler
http://www.eqatec.com/tools/profiler

が良さげですね、また試してみます!

2013/05/31 16:34:26
id:a-kuma3 No.4

回答回数4972ベストアンサー獲得回数2154

ポイント100pt

ProcessExplorer でハンドルの一覧を確認して、リークしてるっぽいオブジェクトの種類や内容から、作ったやつを突き止める、ということを回答しようと思ってたのですが、こちらのほうが良さそう。
http://blog.goo.ne.jp/pianyi/e/fa93d5ea85809c85a7aaf395fc50565f

でかい塊がドカンとリークしているような場合には、一発で解決する可能性も。
小さいつぶつぶがたくさんリークしていると、結構つらいものがありますね。


.NET って真剣に使ったことは無いんですが、ガーベジコレクタはあまり頭が良く無さそうな感じ。

  • Using が使えないところでは、せっせと Nothing を入れておく
  • 自作のクラスは Dispose を実装して、プロパティは積極的に Nothing を入れる
  • System.GC.Collect() を明示的に呼んであげる


回答するにあたって調べたところ、こんな書き込みを見つけました。

  • 循環参照はうまく解決できない。
  • Nothingを入れる前に入っている変数のサイズ分しか解放されないっぽい。
http://i-learn-try-error-and-try.blogspot.jp/2009/09/vbnet.html

後者は、特に信じられないですが、本当だとすると、こんなコードを書かなきゃいけないということになってしまいます。

    a = New ...
        ...
    a = Nothing     ' (?_?)
    a = New ...
        ...
    a = Nothing

こんなの、自分だけじゃ絶対に編み出せない...


なんか、まとまってませんが、何かの参考になれば。

id:halohalolin

a-kuma3さんありがとうございます

WinDbgも挑戦してみたものの、イマイチつうまく動かせなくて挫折していたのですが、検討してみます

なお、なんでも最後はNothing作戦について、ここがメモリーを食っているだろうというところに入れてみたのですが、My.Application.Info.WorkingSetとタスクマネージャ曰くあまり改善していないようです

2013/05/31 16:28:12
id:holoholobird No.5

回答回数574ベストアンサー獲得回数104

ポイント100pt

もう解決しました?
.netのプロファイラならhttp://memprofiler.com/が使いやすかった記憶があります。

http://memprofiler.com/findmemoryleaks.aspx
一度検討してください。

id:halohalolin

holoholobirdさんありがとうございます。

まだ個人的にいろいろあって、EQATEC Profilerをインストールしたところで終わっています。
memprofiler.comもわかりやすそうなので、また検討してみます。

2013/06/04 22:37:25

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません