VC6でのメモリリーク対策
VC6でのメモリリーク対策。http://msdn.microsoft.com/library/ja/jpdnvc60/htm/MemLeaks.asp?frame=true
検出のために以下の3行を追加すれば、メモリリークした場所が特定できると記述されている。
#define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h>
で、やってみた結果がこれ。
Detected memory leaks! Dumping objects -> Z:\program files\microsoft visual studio\vc98\include\crtdbg.h(552) : {128} normal block at 0x004C1940, 209 bytes long. Data: <S ! DIKE> 53 00 00 00 21 82 00 00 C1 00 00 00 44 49 4B 45 Z:\program files\microsoft visual studio\vc98\include\crtdbg.h(552) : {127} normal block at 0x004C1BC0, 12 bytes long. Data: <@ L > 40 19 4C 00 D1 00 00 00 01 00 00 00 Object dump complete.
crtdbg.h の552行目w見ると・・・
#ifdef _CRTDBG_MAP_ALLOC inline void* __cdecl operator new(unsigned int s) { return ::operator new(s, _NORMAL_BLOCK, __FILE__, __LINE__); } #endif /* _CRTDBG_MAP_ALLOC */
見事にヘッダの中で__FILE__と__LINE__がプリプロで展開されてますねw
結論として、#define _CRTDBG_MAP_ALLOCは訳にたたない、と。けれども、先のリンクには有用な情報もあって次の方法を利用する。まずは以下のデバッグ情報の{127}と{128}に注目する。
Detected memory leaks! Dumping objects -> {128} normal block at 0x004C1940, 209 bytes long. Data: <S ! DIKE> 53 00 00 00 21 82 00 00 C1 00 00 00 44 49 4B 45 {127} normal block at 0x004C1BC0, 12 bytes long. Data: <@ L > 40 19 4C 00 D1 00 00 00 01 00 00 00 Object dump complete.
これは、メモリ割り当て番号で127番目と128番目に割り当てられたメモリがリークしているという情報。この割り当て番号を使ってブレークする手順が以下。
- プログラムの先頭でブレーク
- ウォッチウィンドウに_crtBreakAllocを追加。
- 値が-1になっている(たぶん)ので、127にする。
- 実行
これで、127回目にメモリが確保された時にブレークするので、コールスタックを辿ればメモリリークしている箇所が特定できる。いや、知らんかったわ。マルチスレッドの場合は_crtBreakAllocのかわりに{,,msvcrtd.dll}_crtBreakAllocだそう。
ちなみに、crtdbg.hをインクルードしてmainの先頭に以下の行を追加してます。
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);