MFCでのメモリリークの検出方法
Dumping objects ->
メモリリークしたブロックを表示していきます。
G:\Projects\DispBMPDoc.cpp(87) : {158} normal block at 0x014D0040, 921602 bytes long.
G:\Projects\DispBMPDoc.cppというファイルの87行目で割り当てられたブロックです。
プログラムの実行開始から158番目に割り当てられたブロックです。
割り当てられた番地は、0x014D0040番地です。(OSがWin9x、WinNTによっても値が変わってきます)
割り当てられたサイズは、921602 バイトです。
Data: < > 00 FF 00 00 FF 00 00 FF 00 00 FF 00 00 FF 00 00
割り当てられていたブロックに入っているデータの先頭部分が表示されます。
Object dump complete.
メモリリークしたブロックの表示が終わりました。
このような感じで表示されるので、とりあえずファイル名と行番号からメモリを割り当てている場所はわかります。
メモリ開放が行われていないはずなので、追加してください。
ちょっとしたコツ
何番目にメモリを割り当てたかという番号が毎回同じ時
プログラムを実行させて、終了させたときの {} の中の数字が毎回同じというときが有ると思います。
これは、ある条件の時にはちゃんと開放されるが、特定の条件のときに開放されていない場合が多いです。
割り当てるときの番号がある値になったときに、プログラムの実行をとめるとか言うこともできます。
さっきの場合は158番目に割り当てたメモリが、リークしているので158番目にメモリを割り当てる際に、
デバッガが停止するには以下のコードを追加してみてください。
(参考 MSDN キーワード 「デバッグ ルーチン」 _CrtSetBreakAlloc)
#include < crtdbg.h >
void main(void)
{
_CrtSetBreakAlloc(158);
...
}
このコードを実行時の最初に追加すれば、158番目にメモリを割り当てる際にデバッガが停止するので、
どの条件のときにメモリリークが発生しているか突き止めやすいと思います。
その他の場合
マルチスレッドにしてプログラムした場合は、ちょっと再現性とかがなくなってくると思います。
あと、プログラムを実行させたときに行う操作とかをかえるだけで、結果が変わってきます。
どこで割り当てた分がメモリリークを起こしているかは、突き止めることができていると思います。
しかし、どの条件で発生しているかがはっきりとは分からないことが多いです。
そこで私が取った方法は、プログラムを実行させた際に行う処理を毎回同じにして、
メモリを割り当てる順番がある程度にかよってくるまで実行と終了を行います。
たとえば、155-173番目ぐらいに収束してきたら、150番目ぐらいでデバッガが止まるようにします。
そこから、トレースをかけて怪しい部分を重点的に調べました。
それで見つかるようならまだ良いですが、見つからない場合はソース全体をチェックする必要も出てきます。なるべくそうならないように、new や malloc 等のメモリ割り当て関数は注意して使う必要があります。
いまなら、STLのスマートポインタを使うとかすればJAVAのガベージコレクションみたいなことをやってくれるはずです。(私はまだ実際に使ったことがないのですが、Cマガにはそのように書いていました。)