Two of the most common and intractable problems that programmers encounter are overwriting the end of an allocated buffer and memory leaks (failing to free allocations after they are no longer needed). The debug heap provides powerful tools to solve memory allocation problems of this kind.
The Debug versions of the heap functions call the standard or base versions used in Release builds. When you request a memory block, the debug heap manager allocates from the base heap a slightly larger block of memory than requested and returns a pointer to your portion of that block. For example, suppose your application contains the call: malloc( 10 )
. In a Release build, malloc calls the base heap allocation routine and requests an allocation of 10 bytes. In a Debug build, however, malloc calls _malloc_dbg
, which then calls the base heap allocation routine and requests an allocation of 10 bytes plus approximately 36 bytes of additional memory. All the resulting memory blocks in the debug heap connect in a single linked list, ordered according to when they were allocated.
Additional memory allocated by debug heap routines is used for bookkeeping information, for pointers that link debug memory blocks together, and for small buffers on either side of your data to catch overwrites of the allocated region.
Currently, the block header structure used to store the debug heap's bookkeeping information is declared as follows in the dbgint.h header file:
struct _CrtMemBlockTailer { DWORD endd; // fence after data = "ENDD" 0X44444e45 dbg_tailer * next; // next block dbg_tailer * prev; // previous block void * self // pointer to data buffer char * file; // file name int line; // file line number int type; //type of clock size_t size; // size of block long request; // allocation number DWORD nomansland; // header fence = 0xFDFDFDFD } _CrtMemBlockHeader;
The NoMansLand
buffers on either side of the block's user data area are currently 4 bytes in size, and are filled with a known byte value used by the debug heap routines to verify that the limits of the user's memory block are not overwritten. The debug heap also fills new memory blocks with a known value. If you elect to keep freed blocks in the heap's linked list as explained below, these freed blocks are also filled with a known value. Currently, the actual byte values used are as follows:
0xDD
)
0xDD
.
0xCD
)
0xCD
when they are allocated.