有关win32平台下调试堆的描述(Win32 Debug CRT Heap) (下)

上次说到哪了(http://www.cnblogs.com/coolhysteria/archive/2012/09/22/Win32DebugCRTHeap1.html)?哦,对,36字节。

先啥都不说,先给出两个链接,一个来自权威微软的MSDN(http://msdn.microsoft.com/zh-cn/library/bebs9zyz.aspx),一个来此某大神Andrew Birkett的Blog(http://www.nobugs.org/developer/win32/debug_crt_heap.html)。

一段关于调试堆信息结构体的描述如下:

 

Currently, the block header structure used to store the debug heap's bookkeeping information is declared as follows in the DBGINT.H header file:

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];
 */

The NoMansLand buffers on either side of the user data area of the block 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 have not been 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:

NoMansLand (0xFD)

The "NoMansLand" buffers on either side of the memory used by an application are currently filled with 0xFD.

Freed blocks (0xDD)

The freed blocks kept unused in the debug heap's linked list when the _CRTDBG_DELAY_FREE_MEM_DF flag is set are currently filled with 0xDD.

New objects (0xCD)

New objects are filled with 0xCD when they are allocated.

 


 在上一讲中可以看到我们需要的10bytes,全部被初始化为0xCD,也就是说通过这个标志,能很轻易的找到属于我们的数据。
 
 
再给出一张图,可以形象得描述调试堆信息:

这张图可以无缝的对应_CrtMemBlockHeader结构体。我们直接看图说话:

1.0xFDFDFDFD塞满了我的眼球:我们的10bytes数据被一组0xFDFDFDFD围绕在左右,在上面被描述为No mans land,这个就是传说中的《禁闭岛》吗?:D顾名思义,"无人区",自然是意味着这两块区域是不能进入,是禁止被修改的。我们反推一下,如果非要修改这两片区域如何做到呢?毫无疑问,越界呗。也就是说,这个NoMansLand一旦被修改了,那么程序的某个地方肯定是越界了。这样是不是很容易的发现某些堆内存溢出bug了  :P

我们写段代码试试:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 int main(int argc, char **argv)
 5 {
 6     char *p = (char *)malloc(sizeof(char) * 10);
 7     strncpy(p, "hello,boy!!",12);
 8 
 9     
10     free(p);
11     p = NULL;
12 
13     return 0;
14 }

下断,调试:

很明显,溢出分为上溢,和下溢出,这段代码则为上溢出。总之,无论哪种情况,只要发生了,程序便会异常,报错。:(

 

2.看到我,就知道你有多大:我们分配了10 bytes,也就是0xA bytes,调试堆中刚好有个字段描述与0xA相等,没错,你所看到的那4个字节就能瞬间得出咱们分配了多少内存。是不是也很方便? :)

 

3:谁是我的前桌,谁是我的后桌:

依然先给出一段代码:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 int main(int argc, char **argv)
 5 {
 6     char *p = (char *)malloc(sizeof(char) * 10);
 7     char *q = ((char *)malloc(sizeof(char) * 11));
 8     strncpy(p, "hello,boy",10);
 9     strncpy(q, "hello,girl", 11);
10 
11     
12     free(p);
13     p = NULL;
14 
15     return 0;
16 }

然后调试一下:

是不是发现了一些微妙的规律了?所以这里我就不说出来了:D

 

以上三个字段是调试中经常使用到的,剩下的几个字段(用结构体成员描述)确实没用过,但是根据注释也可以知道也是方便调试找到bug具体所在文件,行号等:

    char *szFileName;    // File name
    int nLine;           // Line number
    size_t nDataSize;    // Size of user block
    int nBlockUse;       // Type of block
    long lRequest;       // Allocation number

关于调试堆得内容就先说到这里了,希望能给大家带来一些帮助,同时也加深自己对于知识的记忆和理解:)

所谓理论+实践才是王道,有关调试堆的实际使用技巧请参考:

http://www.cnblogs.com/coolhysteria/archive/2012/10/27/Win32DebugCRTHeapGoAndDo.html

posted on 2012-09-22 12:09  coolhysteria  阅读(812)  评论(0编辑  收藏  举报

导航