自分の役割的にはメモリリークの対応を行うことは本職ではないが、自分で書いたコードなので負い目もある。リリース日は後数日に迫っているので、何とかしなくてはならない。ということで、何とか解決策を見つけたい。
評価担当者によるとメモリリークはXPのタスクマネージャーのメモリ使用量と仮想メモリサイズが増えているとのこと。作ったのはATL-COMのDLL。それを繰り返し呼ぶとそれらが増えるらしい。
さて、疑問。それは本当にメモリリークなのだろうか?本当にメモリリークしていることはどうやったらわかるのだろうか?
色々調べたところ、結局はパフォーマンスモニタ(Perfmon.exe)を使ってProcessのPrivate BytesとVirtual Byteを追跡することが、正解らしい。両者の違いは良くわからなかったが
Private bytes is the total memory that the process has allocated,
Virtual Bytes is the current size in bytes of the virtual address space that the process uses
とのこと。まあ、両方が増えなければ良いのだろうと自分自身を納得させることとした(以下の参考によるとメモリリークの検出にはPrivate bytesの方が適切との記載あり)。
http://support.microsoft.com/kb/268343/en-us?fr=1
http://keicode.com/windows/heap-internals1.php
http://d.hatena.ne.jp/NyaRuRu/20080324/p4
※Private bytesはタスクマネージャーの仮想メモリサイズと一致する。
ということで、本当にメモリリークを起こしているらしい。では、どうやってリーク場所を検出するか?
http://msdn.microsoft.com/ja-jp/library/e5ewb1h3(v=vs.80).aspx
によると、以下によりCRTのリークを検出してくれるらしい。
#define _CRTDBG_MAP_ALLOC
#include
#include
#define new ::new(_NORMAL_BLOCK, __FILE__, __LINE__)
処理の一番最後に
_CrtDumpMemoryLeaks()
を配置することで、その行に処理が移った時点で開放されていない領域を生成したソースコードの行が表示される。
※newのマクロが無いと、どのファイルの何行目でリークしているか分からない
これで完璧!と思ったのだが、結局これはnewもしくはmallocで確保された領域のみを検出するもので、その他のリーク、たとえばSysAllocStringなどで確保された領域は検出してくれないらしい。
やっていることはnewとmallocをマクロとインライン関数でデバッグ用の関数に置き換えているだけ。
また、Auto変数で確保したメモリの開放は、クラスのデストラクタ後に解放されるのでリークとして検出されてしまうので、FalsePositiveがでてしまう。
他に良い方法を探していたところ、以下を見つけた。
http://support.microsoft.com/default.aspx?scid=kb;ja;268343
このストリーミングの手順書はすばらしい。セットアップまで含めて教えてくれる。
これで、何とか怪しそうな部分は特定できた。明日はそこを中心に当たってみよう。
そのたVS2005以降で使える便利な技
http://msdn.microsoft.com/ja-jp/library/350dyxd0.aspx
0 件のコメント:
コメントを投稿