Inside CRT: Debug Heap Management 選擇自 huanghycn 的 Blog
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.
Value | Name | Description |
---|---|---|
0xCD | Clean Memory | Allocated memory via malloc or new but never written by the application. |
0xDD | Dead Memory | Memory that has been released with delete or free. It is used to detect writing through dangling pointers. |
0xFD | Fence Memory | Also known as "no mans land." This is used to wrap the allocated memory (like surrounding it with fences) and is used to detect indexing arrays out of bounds. |
0xAB | (Allocated Block?) | Memory allocated by LocalAlloc(). |
0xBAADF00D | Bad Food | Memory allocated by LocalAlloc() with LMEM_FIXED, but not yet written to. |
0xCC | When the code is compiled with the /GZ option, uninitialized variables are automatically assigned to this value (at byte level). |
If you take a look at DBGHEAP.C, you can see how some of these values are defined:
static unsigned char _bNoMansLandFill = 0xFD; /* fill no-man's land with this */static unsigned char _bDeadLandFill = 0xDD; /* fill free objects with this */static unsigned char _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.
Function | Description |
---|---|
malloc | C/C++ function that allocates a block of memory from the heap. The implementation of the C++ operator new is based on malloc. |
_malloc_dbg | Debug version of malloc; only available in the debug versions of the run-time libraries. _malloc_dbg is a debug version of the malloc function. When _DEBUG is not defined, each call to _malloc_dbg is reduced to a call to malloc. Both malloc and _malloc_dbg allocate a block of memory in the base heap, but _malloc_dbg offers several debugging features: buffers on either side of the user portion of the block to test for leaks, a block type parameter to track specific allocation types, and filename/linenumber information to determine the origin of allocation requests. |
free | C/C++ function that frees an allocated block. The implementation of C++ operator delete is based on free. |
_free_dbg | Debug version of free; only available in the debug versions of the run-time libraries. The _free_dbg function is a debug version of the free function. When _DEBUG is not defined, each call to _free_dbg is reduced to a call to free. Both free and _free_dbg free a memory block in the base heap, but _free_dbg accommodates two debugging features: the ability to keep freed blocks in the heap's linked list to simulate low memory conditions and a block type parameter to free specific allocation types. |
LocalAlloc 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 = new char[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 4typedef struct _CrtMemBlockHeader{ struct _CrtMemBlockHeader * pBlockHeaderNext; struct _CrtMemBlockHeader * pBlockHeaderPrev; char * szFileName; int nLine; size_t nDataSize; int nBlockUse; long lRequest; unsigned char gap[nNoMansLandSize]; /* followed by: * unsigned char data[nDataSize]; * unsigned char anotherGap[nNoMansLandSize]; */} _CrtMemBlockHeader;
It stores the following information:
Field | Description |
---|---|
pBlockHeaderNext | A pointer to the next block allocated, but next means the previous allocated block because the list is seen as a stack, with the latest allocated block at the top. |
pBlockHeaderPrev | A pointer to the previous block allocated; this means the block that was allocated after the current block. |
szFileName | A pointer to the name of the file in which the call to malloc was made, if known. |
nLine | The line in the source file indicated by szFileName at which the call to malloc was made, if known. |
nDataSize | Number of bytes requested |
nBlockUse | 0 - Freed block, but not released back to the Win32 heap 1 - Normal block (allocated with new/malloc) 2 - CRT blocks, allocated by CRT for its own use |
lRequest | Counter incremented with each allocation |
gap | 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.)
Address | after HeapAlloc() | after malloc() |
---|---|---|
00320FD8 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.
Address | Before HeapFree() | After HeapFree() |
---|---|---|
00320FD8 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:
Address (hex) | Offset | HeapAlloc | malloc | Free before HeapFree | Free after HeapFree | Description |
---|---|---|---|---|---|---|
00320FD8 | -40 | 01090009 | 01090009 | 01090009 | 01090082 | Win32 Heap info |
00320FDC | -36 | 001807E8 | 001807E8 | 0018075E | 0018045E | Win32 Heap info |
00320FE0 | -32 | BAADF00D | 00320798 | DDDDDDDD | 00322BE0 | pBlockHeaderNext |
00320FE4 | -28 | BAADF00D | 00000000 | DDDDDDDD | 00320178 | pBlockHeaderPrev |
00320FE8 | -24 | BAADF00D | 00000000 | DDDDDDDD | FEEEEEEE | szFileName |
00320FEC | -20 | BAADF00D | 00000000 | DDDDDDDD | FEEEEEEE | nLine |
00320FF0 | -16 | BAADF00D | 0000000C | DDDDDDDD | FEEEEEEE | nDataSize |
00320FF4 | -12 | BAADF00D | 00000001 | DDDDDDDD | FEEEEEEE | nBlockUse |
00320FF8 | -8 | BAADF00D | 0000002E | DDDDDDDD | FEEEEEEE | lRequest |
00320FFC | -4 | BAADF00D | FDFDFDFD | DDDDDDDD | FEEEEEEE | gap (no mans land) |
00321000 | 0 | BAADF00D | CDCDCDCD | DDDDDDDD | FEEEEEEE | Data requested |
00321004 | +4 | BAADF00D | CDCDCDCD | DDDDDDDD | FEEEEEEE | Data requested |
00321008 | +8 | BAADF00D | CDCDCDCD | DDDDDDDD | FEEEEEEE | Data requested |
0032100C | +12 | BAADF00D | FDFDFDFD | DDDDDDDD | FEEEEEEE | No mans land |
00321010 | +16 | ABABABAB | ABABABAB | ABABABAB | FEEEEEEE | Win32 Heap info |
00321014 | +20 | ABABABAB | ABABABAB | ABABABAB | FEEEEEEE | Win32 Heap info |
00321018 | +24 | 00000000 | 00000000 | 00000000 | FEEEEEEE | Win32 Heap info |
0032101C | +28 | 00000000 | 00000000 | 00000000 | FEEEEEEE | Win32 Heap info |
00321020 | +32 | 00090079 | 00090079 | 00090079 | FEEEEEEE | Win32 Heap info |
00321024 | +36 | 00EE04EE | 00EE04EE | 00EE04EE | FEEEEEEE | Win32 Heap info |
00321028 | +40 | 00320540 | 00320540 | 00320540 | FEEEEEEE | Win32 Heap info |
0032102C | +44 | 00320540 | 00320540 | 00320540 | FEEEEEEE | Win32 Heap info |
About the Author
Marius Bancila is a software developer working for a company that provides industrial automation solutions, but he is mainly focused on GUI design with MFC. When he discovered the .NET framework quickly fell inlove. He considers that CodeGuru is the best place on internet to spend time on.
相關推薦
Inside CRT: Debug Heap Management 選擇自 huanghycn 的 Blog
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 dealloc
Asp .Net Mvc在DeBug模式下設定自定義IP
首先開啟所在專案下的.vs檔案(檢視隱藏檔案) 開啟config下的applicationhost.config檔案 往下拖大概100多行的位置,複製一下binding,然後設定本地ip,如果是設定ip的而非locolhost需要以管理員身份執行,才能開啟,之後重啟vs即可。 P
關於Microsoft SQL Server Management Studio自定義安裝時不能更改安裝路徑或只能更改一個或兩個問題的解決
1.首先,肯定你在裝SQLServer之前裝了VS,然後你的C盤裡面會在裡面新建了SQLServer的資料夾,所以你在後面裝SQLServer的時候只能更改一個路徑。 2.解決方法:解除安裝VS,然後再裝SQLServer,進入控制面板,然後把 這些解除安裝了(我圖片裡面
程式設計師跳槽到國企之後,表示打死不去阿里騰訊,選擇自甘墮落下去
作為程式設計師,是繼續在網際網路打拼,還是投入國企懷抱,這一直是個頗受爭議的話題。最近有位網友,就在社群裡發出了自己從網際網路創業公司,跳槽到國企後的感慨。他原本在一家創業公司做前端,每天被老闆嫌棄工作沒做好,加班不夠多,所以一怒之下,離職加入國企,沒想到,新工作不僅工作輕鬆,月薪也非常可觀,達到驚
Android配置build.gradle的buildTypes動態自動維護debug和release包自定義欄位變數值
Android配置build.gradle的buildTypes動態自動維護debug和release包自定義欄位變數值 在Android編譯出包階段,debug包和正式的release有時候需要作出有所區別的調整。 比如最常見的是App應用程式中Log日誌輸出開關的控制。開發者希望在deb
安卓仿iphone日期選項器 仿iphone日期選擇自定義控制元件
原來的DatePicker總有這樣那樣的不如意,看到ipad的日期選擇,感覺很好,如果google android date like iphone, 得到Android Wheel,專案地址:https://code.google.com/p/android-wheel/
Google Friendly的網站設計 選擇自 Kamus 的 Blog (轉載,版權歸原作者所有)
<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"> </script>我轉載自簡樸生活的blog,不知道他轉載自哪
C++ Builder下三種UDP通訊實現方法的比較 選擇自 findheart 的 Blog
C++ Builder下三種UDP通訊實現方法的比較 選擇自 findheart 的 Blog 關鍵字 C++ Builder下三種UDP通訊實現方法的比較 出處 主要討論一下資料的接受:1.NMUDP控制元件 這個控制元件使用起來比較簡單,設定
C++ operator new[]和Debug Heap
如果在VS2005下面想用CRT Debug Heap來除錯Memory Leak,最後可以用_CrtDumpMemoryLeaks把所有的leak打印出來。嘗試下面的程式碼,會怎樣: #include "stdafx.h" #ifdef _DEBUG #define _CRTDBG_MAP_ALL
QTableView表格控制元件區域選擇-自繪選擇區域
目錄 一、開心一刻 二、概述 三、效果展示 四、實現思路 1、繪製區域 2、繪製邊框 3、繪製 五、相關文章
eclipse 集成Maven(轉自:http://blog.csdn.net/wode_dream/article/details/38052639)
lin loser 說明 位置 到你 ide lan core fontsize 當自己越來越多的接觸到開源項目時,發現大多數的開源項目都是用maven來夠建的。並且在開發應用時,也越來越意識到maven的確會解決很多問題,如果你要了解maven,可以參考:Maven入門
laravel session使用 轉自http://blog.csdn.net/angle_hearts/article/details/53923782
com lar new get ssi name sym 存儲 angle use Symfony\Component\HttpFoundation\Session\Session;//存儲session$session = new Session;$session->
sed和awk的一些使用【轉載自http://blog.sina.com.cn/s/blog_6561ca8c0102we0o.html】
blog printf begin 文件中 字符串 filename hello 選項 sina 在linux中,awk和sed命令對於快速的文本編排非常靈活有用。對文本插入列的操作也可以使用sed或者awk命令來處理,下面簡單介紹: 如果想要在指定列前插入字符串RR,
Annovar註釋說明【轉載自http://blog.csdn.net/u013816205/article/details/51262289】
probably scores hit bar package 文件轉換 命名 gre 下載 ANNOVAR是一個perl編寫的命令行工具,能在安裝了perl解釋器的多種操作系統上 執行。允許多種輸入文件格式,包括最常被使用的VCF格式。輸出文件也有多種格式,包括註釋過的V
jquery中使用event.target的幾點說明 (轉自http://blog.csdn.net/zm2714/article/details/8119642)
board ngs 使用 net spa dtd meta xhtml function jquery中使用event.target的幾點說明 event.target 說明:引發事件的DOM元素。 this和event.target的區別 js中事件是
linux音頻alsa-uda134x驅動文檔閱讀之一轉自http://blog.csdn.net/wantianpei/article/details/7817293
發出 hand 增加 int chang == 音頻 set device 前言 目前,linux系統常用的音頻驅動有兩種形式:alsa oss alsa:現在是linux下音頻驅動的主要形式,與簡單的oss兼容。oss:過去的形式而我們板子上的uda1341用的就是als
Go語言庫之strconv包(轉載自--http://blog.csdn.net/alvine008/article/details/51283189)
整型 print 特殊 imp size 無符號 this http 相差 golang strconv.ParseInt 是將字符串轉換為數字的函數 func ParseInt(s string, base int, bitSize int) (i int64, err
SSIS獲得Excel行號(轉自http://blog.csdn.net/zplume/article/details/19113911)
number source 行數 put article 情況 art r+ 數據庫 問題描述: 首先個人並不推薦將Excel作為數據源,因為Excel單元格式會引起特別多的數據轉換問題,例如:單元格裏明明是2.89,但SSIS抽取到數據庫裏面之後卻變成了2.8899999
極大極小搜索思想+(α/β)減枝 【轉自-----https://blog.csdn.net/hzk_cpp/article/details/79275772】
ima 基本 個數 博弈論 數字 這就是 pre -- 繼續 極大極小搜索,即minimax搜索算法,專門用來做博弈論的問題的暴力. 多被稱為對抗搜索算法. 這個搜索算法的基本思想就是分兩層,一層是先手,記為a,還有一層是後手,記為b. 這個搜索是認為這a與b的利益關
pycharm的斷點除錯【轉自https://blog.csdn.net/weixin_39198406/article/details/78873120】
1. show execution point (F10)顯示目前專案所有斷點2. step over (F8)下一步但僅限於設定斷點的檔案3. step into (F7)執行下一行4. step into my code (Alt+Shift+F7)執行下一行但忽略libraries(匯入庫的語句)5.