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

首先给出本次讨论话题的目录:

---------------------------------------------------------------------------------------------------------------

1.有关win32平台下调试堆的描述(上)

http://www.cnblogs.com/coolhysteria/archive/2012/09/22/Win32DebugCRTHeap1.html

2.有关win32平台下调试堆的描述(下)

http://www.cnblogs.com/coolhysteria/archive/2012/09/22/Win32DebugCRTHeap2.html

3.(转载)有关win32平台下调试堆的描述(实战篇)

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

----------------------------------------------------------------------------------------------------------------

 

心情莫名的好,索性就早早的起来了。这几天帮同学调试了些许程序,遇到了不少有关数组越界,堆指针引用错误等一系列问题,于是就准备写篇文章详细的描述一下如何发现,并避免这类难以发现且难以避免的问题。当然,在这里首先得感谢一位朋友,名字就不说了,因为他担心被人肉了(just a joke):P。

这篇文章的目的仅仅为了描述一个结构,有关调试堆(Win32 Debug CRT Heap )的结构(_CrtMemBlockHeader)。这个暂时放在一边,我们先聊聊别的话题。

 

1.什么是堆(heap),什么是栈(stack)?

在计算机中,一切运行中的数据都存放在内存中,以方便CPU取指令以及执行指令。

但是内存又划分为堆,栈,以及静态区。

栈:栈是由编译器维护(分配和释放)的一块比较小的内存区域(vc6.0下默认为1M,也可以在设置中更改:Project->Setting->Link中的output,其中reserve和commit字段),用于存放局部变量,以及函数栈帧(也就是说函数的压参,函数调用,使用参数,函数返回都是在栈中完成的),且栈的生长方向是从高地址向低地址增长。

堆:堆是由程序员维护(分配和释放)的一块比较大的内存区域(32bit系统下,理论可以达到4G),当然,程序结束的后,操作系统会介入进来释放掉掉分配的堆内存。一般在程序中看到malloc,realloc等库函数以及C++的new运算符都是在堆中分配内存,由这一点也可以看出,堆是靠这些库函数的一系列算法来实现的,所以分配堆得效率远远没栈高,同时也会导致我们在使用堆的时候容易出现很多问题。且堆的生长方向是从低地址向高地址增长。

 

2.堆和栈怎么使用,在哪看?

栈:

给出代码和示意图,用于详细直观描述栈

1 int main(int argc, char **argv)
2 {
3     int tmp = argc;
4 
5     return 0;
6 }

OD中找到代码段的main函数调用(不要忘记了main函数也是函数 :P)如下:

函数调用,栈帧的情况如下:(od调试时候查看stack窗口)

 

 

堆:

给出代码和示意图,用于详细直观描述堆:

#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
    char *p = (char *)malloc(sizeof(char) * 10);
    strncpy(p, "hello,boy",10);
    
    free(p);
    p = NULL;

    return 0;
}

malloc调用后,在内存中定位p,由p指向的那块区域便是我们分配在堆中的10bytes。(在vc++6.0中调试时候查看memory窗口)

 

3.什么是调试堆?有什么作用?

对于程序员来说,最蛋疼的时候便是遇到bug却找不到bug所在,找到bug却不知道如何修复bug。而比较低级的错误却刚好是难以避免的,比如数组越界,指针错误引用。在这一方面微软给大家提供了一个很方便的东西------调试堆。

首先回到刚刚第二段代码,在char *p = (char *)malloc(sizeof(char) * 10);执行后,我们理所当然的会认为操作系统给咱们分配了10个字节的大小,让我们再次看看这句话执行后,内存中到底有些什么东西。

 

再看看给堆内存中拷贝字符串后的情况:

以上两张图仔细比较之后,很容易发现,确实多分配了36个字节。先掉掉大家胃口,休息一会,关于这36个字节,将会在下一章节中(http://www.cnblogs.com/coolhysteria/archive/2012/09/22/Win32DebugCRTHeap2.html)详细描述。:D

大家也可以先自己研究一下,肯定能或多或少发现一些小细节 :D

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

导航