\n |
[ トップページ ]
[ ____CommandPrompt ]
[ ____JScript ]
[ ____MySQL ]
[ ____Cygwin ]
[ ____Java ]
[ ____Emacs ]
[ ____Make ]
[ ____Perl ]
[ ____Python ]
[ ____OpenGL ]
[ ____C# ]
[ ____StyleSheet ]
[ ____C++ ]
[ ____Winsock ]
[ ____Thread ]
[ ____VisualStudio ]
[ ____C ]
[ ____Win32API ]
[ ____Lua ]
[ ____PhotoShop ]
ヘッダ検索
■ デバッグCRTライブラリ(DebugLibrary)
VisualC++ にはデバッグライブラリがあるため
メモリリークなどを検出できる。
メモリリークを検出するには次のマクロを定義することで、実装する処理を切り替える
#define __CRTDBG_MAP_ALLOC
#include< crtdbg.h>
int main() {
// 利用したいデバッグ機能をフラグで指定する。
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
void *p = malloc( 256 );
// プログラムの終了時にリークをチェックする。
_CrtDumpMemoryLeaks();
return 0;
}
ビルド設定は次のようにする。
デバッグ版のCRTを利用するため, コンパイル時のオプションで /MTd を選択する必要がある。
cl /c -D_DEBUG /MTd -Od -Zi -W3 test.cpp && link -verbose:lib /debug test.obj
// BAD
cl /c -D_DEBUG /MT -Od -Zi -W3 test.cpp && link -verbose:lib /debug test.obj
WARNING
_CrtDumpMemoryLeaks のログは OutputDebugString() として出力されるため
コンソールへの stdout, stderr には出力されない。
■ _CrtSetDbgFlag
SYNTAX
int _CrtSetDbgFlag(
int newFlag
);
DESC
デバッグ用のヒープマネージャのオプションを指定する。
_CRTDBG_ALLOC_MEM_DF
デバッグヒープ割り当てを有効にする。
_CRTDBG_LEAK_CHECK_DF
プログラムの終了時に _CrtDumpMemoryLeaks を呼び出して、メモリ リークのチェックを自動的に実行する。
■ _CrtSetReportMode
SYNTAX
int _CrtSetReportMode(
int reportType, タイプ ( _CRT_WARN _CRT_ERROR _CRT_ASSERT )
int reportMode 出力先
);
DESC
_CrtDbgReport、_ASSERT マクロ、_ASSERTE マクロ、_ASSERT マクロ、_ASSERTE マクロ、
_RPT、_RPTF、_RPTW、_RPTFW のマクロ、_RPT、_RPTF、_RPTW、_RPTFW のマクロ などの
_CrtDbgReport、_CrtDbgReportW
を呼び出すすべてのマクロが生成する特定のレポートの種類の出力先を指定する。
(デバッグ バージョンのみ)
_CRTDBG_MODE_DEBUG
メッセージをデバッガの出力ウィンドウ
_CRTDBG_MODE_FILE
ユーザー指定のファイル ハンドル
_CrtSetReportFile を呼び出して、出力先となるファイルまたはストリームを定義します。
_CRTDBG_MODE_WNDW
メッセージ ボックスを作成し
メッセージと Abort、Retry、Ignore の各ボタンを表示する。
_CRTDBG_REPORT_MODE
指定された reportType の reportMode を返します。
アサートの出力を stderr とダイアログボックスに表示する。
_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_WNDW );
_CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR );
_ASSERTE( !"test" );
■ _CrtSetReportFile
SYNTAX
_HFILE _CrtSetReportFile(
int reportType,
_HFILE reportFile
);
DESC
stderr にアサート結果を出力する。
_CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR );
HANDLE h = CreateFile("c:\\log.txt", GENERIC_WRITE,
FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN, h);
_RPT0(_CRT_WARN,"file message\n");
CloseHandle(h);
■ _CrtSetDumpClient
SYNTAX
_CRT_DUMP_CLIENT _CrtSetDumpClient(
_CRT_DUMP_CLIENT dumpClient
);
WARNING
これは _CLIENT_BLOCK 型なので _NORMAL_BLOCK 型のリークにはフックできない。
DESC
アプリケーションは、_CLIENT_BLOCK メモリ ブロックに格納されているオブジェクトをダンプする独自の関数を
C ランタイムデバッグのメモリ ダンププロセスにフックできる
この結果、_CrtMemDumpAllObjectsSince や _CrtDumpMemoryLeaks などのデバッグ ダンプ関数が
_CLIENT_BLOCK メモリ ブロックをダンプするたびに、
アプリケーションのダンプ関数も呼び出される。
_CrtSetDumpClient を使用すると
簡単な方法でメモリ リークを検出し、_CLIENT_BLOCK ブロックに格納されているデータのコンテンツを検証またはレポートできます。
_DEBUG が未定義の場合、_CrtSetDumpClient の呼び出しはプリプロセスで削除される。
_CrtSetDumpClient は、dumpClient で指定されたアプリケーション定義の
新しいダンプ関数をインストールし、前回定義されていたダンプ関数を返す。
クライアント ブロックのダンプ関数の例は、次のとおりです。
void DumpClientFunction(
void *userPortion,
size_t blockSize
);
userPortion
メモリブロックのユーザー データ領域の先頭へのポインタです。
blockSize
割り当てられたメモリ ブロックのサイズをバイト単位で指定する。
クライアント ブロックのダンプ関数は、void を返す必要がある。
_CrtSetDumpClient に渡されるクライアント ダンプ関数へのポインタは
_CRT_DUMP_CLIENT 型で、Crtdbg.h で次のように定義される。
typedef void (__cdecl *_CRT_DUMP_CLIENT)( void *, size_t );
■ _CrtDumpMemoryLeaks
SYNTAX
int _CrtDumpMemoryLeaks();
DESC
メモリ リークの発生時に、デバッグ ヒープ内のメモリ ブロックをすべてダンプする。
RET
true : リークがある
false : リークなし
■ _CrtSetBreakAlloc
SYNTAX
long _CrtSetBreakAlloc(
long lBreakAlloc // BP を設定する割り当て順序番号
);
DEP
< crtdbg.h>
DESC
アプリケーションは、特定のメモリ割り当て位置にブレークポイントを設定し、
要求元までトレースすることによって、メモリ リークを検出できます
使用されるオブジェクト割り当て順序番号は、ヒープへの割り当て時にメモリブロックに割り当てられた
シーケンシャル番号です
_DEBUG が未定義の場合、_CrtSetBreakAlloc の呼び出しはプリプロセスで削除されます
オブジェクト割り当て順序番号は
Crtdbg.h で定義されている _CrtMemBlockHeader 構造体の lRequest フィールドに格納されます
デバッグ ダンプ関数のいずれかが出力するメモリ ブロック情報のレポートでは
中かっこで囲まれて {36} のように表示されます
■ _CrtIsValidHeapPointer();
POINT
Debug Library のみにあるため, /MTd にしないと LinkError
つまり Option を切り替えることでリンクする Library を変更しているということ
dll 内の heap を解放すると crash する
参照するだけなら 問題ない。
char *p = testdll();
_ASSERTE( _CrtIsValidHeapPointer(p) );
// これで落ちる
delete p;
|
|
NINJAIDX 15