メモリ管理とデバッグ ヒープ
このトピックの内容は、次の製品に該当します。
エディション |
Visual Basic |
C# |
F# |
C++ |
Web Developer |
---|---|---|---|---|---|
Express |
ネイティブのみ |
||||
Pro、Premium、Ultimate |
ネイティブのみ |
割り当てたバッファーの末尾を超えて書き込みをしてしまうこと、およびメモリ リーク (不要になったメモリ割り当てを解放し忘れること) は、プログラマが経験する問題の中で最も一般的でありながら、最もやっかいなものです。 デバッグ ヒープは、このようなメモリ割り当ての問題を解決するための強力なツールとなります。
デバッグ バージョンのヒープ関数
デバッグ バージョンのヒープ関数は、リリース ビルドで使用される標準バージョン (基本バージョン) の関数を呼び出します。 メモリ ブロックの割り当てが要求されると、デバッグ ヒープ マネージャーは、要求されたサイズより少し大きめのメモリ ブロックをベース ヒープから割り当て、このブロック内のユーザー領域へのポインターを返します。 たとえば、アプリケーション中で malloc( 10 ) という呼び出しをしたとします。 リリース ビルドでは、malloc はベース ヒープ割り当てルーチンを呼び出し、10 バイトの割り当てを要求します。 一方、デバッグ ビルドでは、malloc は _malloc_dbg を呼び出します。それはベース ヒープ割り当てルーチンを呼び出し、10 バイトに約 36 バイト加えたメモリを割り当てるよう要求します。 デバッグ ヒープに割り当てられたすべてのメモリ ブロックは、単一のリンク リストとして、割り当てられた順番で連結されます。
デバッグ ヒープ ルーチンによって余分に割り当てられたメモリは、ブックキーピング情報や、デバッグ用のメモリ ブロックを連結するためのポインター用に使用されます。また、割り当てられた領域を超えて行われた書き込みを検出するために割り当て領域の前後に確保される小さなバッファーとしても使用されます。
現在、デバッグ ヒープ用のブックキーピング情報を格納するために使用されるブロック ヘッダー構造体は、DBGINT.H ヘッダー ファイルで次のように宣言されています。
typedef struct _CrtMemBlockHeader
{
// Pointer to the block allocated just before this one:
struct _CrtMemBlockHeader *pBlockHeaderNext;
// Pointer to the block allocated just after this one:
struct _CrtMemBlockHeader *pBlockHeaderPrev;
char *szFileName; // File name
int nLine; // Line number
size_t nDataSize; // Size of user block
int nBlockUse; // Type of block
long lRequest; // Allocation number
// Buffer just before (lower than) the user's memory:
unsigned char gap[nNoMansLandSize];
} _CrtMemBlockHeader;
/* In an actual memory block in the debug heap,
* this structure is followed by:
* unsigned char data[nDataSize];
* unsigned char anotherGap[nNoMansLandSize];
*/
ブロックのユーザー データ領域の前後に確保される NoMansLand バッファーのサイズは、現在は 4 バイトです。このバッファーには既知のバイト値が格納されており、デバッグ ヒープ ルーチンは、この値を使用してメモリ ブロックのユーザー領域の境界を越えて書き込みが行われていないかどうかを検証します。 デバッグ ヒープは、新しく確保されたメモリ ブロックにも既知の値を格納します。 解放されたブロックをヒープのリンク リストに保持するように設定した場合は、解放済みのブロックにも既知の値が格納されます。 現在、実際に使用されているバイト値は次のとおりです。
NoMansLand (0xFD)
アプリケーションが使用するメモリ領域の前後に確保される "NoMansLand" バッファーには 0xFD が格納されます。解放済みのブロック (0xDD)
_CRTDBG_DELAY_FREE_MEM_DF フラグが設定されている場合、解放済みのブロックは使用されずにヒープのリンク リストに保持され、0xDD が格納されます。新規オブジェクト (0xCD)
新規オブジェクトには、メモリの割り当て時に 0xCD が格納されます。