(转)Inside CRT: Debug Heap Manage
luyued 发布于 2011-01-13 02:01 浏览 N 次http://www.codeguru.com/cpp/w-p/win32/tutorials/article.php/c9535/
Learn how heap management is done in a debug build
Rating:
Marius Bancila (view profile)
April 4, 2005
Environment: Visual C++ 6.0
When you compile a debug build of your program with Visual Studio and run it in debugger, you can see that the memory allocated or deallocated has funny values, such as 0xCDCDCDCD or 0xDDDDDDDD. This is the result of the work Microsoft has put in to detect memory corruption and leaks in the Win32 platform. In this article, I will explain how memory allocation/deallocation is done via new/delete or malloc/free.
First, I will explain what all these values that you see, like CD, DD, and so forth, mean.
If you take a look at DBGHEAP.C, you can see how some of these values are defined:
staticunsignedchar _bNoMansLandFill = 0xFD; /* fill no-man's land with this */staticunsignedchar _bDeadLandFill = 0xDD; /* fill free objects with this */staticunsignedchar _bCleanLandFill = 0xCD; /* fill new objects with this */
Before going any further, take a look at the memory management function that I will refer in this article.
GlobalAlloc Win32 API to allocate the specified number of bytes from the heap. Windows memory management does not provide a separate local heap and global heap.LocalFree
GlobalFree Win32 API free the specified local memory object and invalidates its handle.HeapAlloc Win32 API allocates a block of memory from a heap. The allocated memory is not movable.HeapFree Win32 API frees a memory block allocated from a heap by the HeapAlloc or HeapReAlloc function.
There are many other functions that deal with memory management. For a complete view please refer to MSDN.
Note: Because this article is about memory management in a debug build, all the references to malloc and free in the following are actually references to their debug versions, _malloc_dbg and _free_dbg.
Compile the following code and run it in the debugger, walking step by step into it to see how memory is allocated and deallocated.
int main(int argc, char* argv[]){ char *buffer = newchar[12]; delete [] buffer; return 0;}
Here, 12 bytes are dynamically allocated, but the CRT allocates more than that by wrapping the allocated block with bookkeeping information. For each allocated block, the CRT keeps information in a structure called _CrtMemBlockHeader, which is declared in DBGINT.H:
#define nNoMansLandSize 4
typedefstruct _CrtMemBlockHeader
{
struct _CrtMemBlockHeader * pBlockHeaderNext;
struct _CrtMemBlockHeader * pBlockHeaderPrev;
char * szFileName;
int nLine;
size_t nDataSize;
int nBlockUse;
long lRequest;
unsignedchar gap[nNoMansLandSize]; /* followed by: * unsigned char data[nDataSize]; * unsigned char anotherGap[nNoMansLandSize]; */
} _CrtMemBlockHeader;
It stores the following information:
1 - Normal block (allocated with new/malloc)
2 - CRT blocks, allocated by CRT for its own uselRequest Counter incremented with each allocationgap A zone of 4 bytes (in the current implementation) filled with 0xFD, fencing the data block, of nDataSize bytes. Another block filled with 0xFD of the same size follows the data.
Most of the work of heap block allocation and deallocation are made by HeapAlloc() and HeapFree(). When you request 12 bytes to be allocated on the heap, malloc() will call HeapAlloc(), requesting 36 more bytes.
blockSize = sizeof(_CrtMemBlockHeader) + nSize + nNoMansLandSize;
malloc requests space for the 12 bytes we need (nSize), plus 32 bytes for the _CrtMemBlockHeader structure and another nNoMansLandSize bytes (4 bytes) to fence the data zone and close the gap.
But, HeapAlloc() will allocate even more bytes: 8 bytes below the requested block (that is, at a lower address) and 32 above it (that is, at a bigger address). It also initializes the requested block to 0xBAADF00D (bad food).
Then, malloc() fills the _CrtMemBlockHeader block with information and initializes the data block with 0xCD and no mans land with 0xFD.
Here is a table that shows how memory looks after the call to HeapAlloc() and after malloc() returns. For a complete situation, see the last table. (Note: All values are in hex.)
00320FDC
00320FE0
00320FE4
00320FE8
00320FEC
00320FF0
00320FF4
00320FF8
00320FFC
00321000
00321004
00321008
0032100C
00321010
00321014
00321018
0032101C
00321020
00321024
00321028
0032102C 09 00 09 01
E8 07 18 00
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
0D F0 AD BA
AB AB AB AB
AB AB AB AB
00 00 00 00
00 00 00 00
79 00 09 00
EE 04 EE 00
40 05 32 00
40 05 32 00 09 00 09 01
E8 07 18 00
98 07 32 00
00 00 00 00
00 00 00 00
00 00 00 00
0C 00 00 00
01 00 00 00
2E 00 00 00
FD FD FD FD
CD CD CD CD
CD CD CD CD
CD CD CD CD
FD FD FD FD
AB AB AB AB
AB AB AB AB
00 00 00 00
00 00 00 00
79 00 09 00
EE 04 EE 00
40 05 32 00
40 05 32 00
Colors:
- Green: win32 bookkeeping info
- Blue: block size requested by malloc and filled with bad food
- Magenta: _CrtMemBlockHeader block
- Red: no mans land
- Black: requested data block
In this example, after the call to malloc() returns, buffer will point to memory address 0x00321000.
When you call delete/free, the CRT will set the block it requested from HeapAlloc() to 0xDD, indicating this is a free zone. Normally after this, free() will call HeapFree() to give back the block to the Win32 heap, in which case the block will be overwritten with 0xFEEEEEEE, to indicate Win32 heap free memory.
You can avoid this by using the CRTDBG_DELAY_FREE_MEM_DF flag to _CrtSetDbgFlag(). It prevents memory from actually being freed, as for simulating low-memory conditions. When this bit is on, freed blocks are kept in the debug heap's linked list but are marked as _FREE_BLOCK. This is useful if you want to detect dangling pointers errors, which can be done by verifying if the freed block is written with 0xDD pattern or something else. Use _CrtCheckMemory() to verify the heap.s integrity.
The next table shows how the memory looks during the free(), before HeapFree() is called and afterwards.
00320FDC
00320FE0
00320FE4
00320FE8
00320FEC
00320FF0
00320FF4
00320FF8
00320FFC
00321000
00321004
00321008
0032100C
00321010
00321014
00321018
0032101C
00321020
00321024
00321028
0032102C 09 00 09 01
5E 07 18 00
DD DD DD DD
DD DD DD DD
DD DD DD DD
DD DD DD DD
DD DD DD DD
DD DD DD DD
DD DD DD DD
DD DD DD DD
DD DD DD DD
DD DD DD DD
DD DD DD DD
DD DD DD DD
AB AB AB AB
AB AB AB AB
00 00 00 00
00 00 00 00
79 00 09 00
EE 04 EE 00
40 05 32 00
40 05 32 00 82 00 09 01
5E 04 18 00
E0 2B 32 00
78 01 32 00
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
EE FE EE FE
Colors:
- Green: win32 bookkeeping info
- Blue: CRT block filled with dead memory
- Gray: memory given back to win32 heap
The two tables above are put in a single, more detailed, table below:
- 06-30· 引用 (原创)陌上花.赏菊
- 06-21· “感动南京”人物谢二喜
- 06-21· 男士服饰搭配的基本原则
- 06-21· 程式内衣简介
- 06-21· 搭配点评 无论你身材、肤
- 06-21· 品牌内衣
- 06-21· 红脸蛋与绿西瓜
- 06-19· [神马]【2011-03-03】外贸童
- 06-19· 济南小商品 济南大明湖东
- 06-19· 妒
- 06-19· 2011年03月24日
- 06-19· 一个小小的纹身
- 06-19· 女装,女鞋,超值店
- 06-19· 谈谈购房体会
- 06-19· [转载]中医肾病用药体会
- 06-19· 我的读书心得体会
- 06-19· [转载]学习精细化管理写了
- 06-19· 谈谈拜《楞严经》的体会
- 06-18· 上海基本药物增补高价外
- 06-18· 辉瑞与百时美施贵宝叫停