HEAP: Free Heap block XXXX modified at XXXX after it was freed 的处理

 HEAP: Free Heap block XXXX modified at XXXX after it was freed 的处理

环境:Windows XP SP3,VC2008

在开发过程中,偶尔会遇到程序提示 HEAP异常的情况

以下讨论限于Debug模式

常见提示如下

vc的输出窗口提示:

翻译过来就是 某个已经释放的堆空间被修改了,就是某块动态申请(malloc/new)的内存,在它被释放(free/delete)后,又被使用了。

比如编写了如下的代码,就会有这个提示

以上代码比较简单,可以很容易的看出问题出在哪里,当代码量比较大的时候,就不是一眼就能看出来了。

在以上代码中,调试器断在了line31,那是一句申请空间的语句,当申请空间的时候,crt会进行一定的检查,所以就发现了这个heap 错误。

为了查找是哪一个地方的内存错误,需要借助 VC 提供的几个 heap debug 函数。

在程序的开始部分加入

它们会把malloc/free函数映射到dbg版的函数上去,那几个函数有调用时的文件名和函数行数信息,方便定位代码位置

修改后的代码如下

_CrtSetDbgFlag() 是设置调试标志,这里设置了_CRTDBG_CHECK_ALWAYS_DF(每一次malloc/free等操作,都对内存进行检查) 和 _CRTDBG_DELAY_FREE_MEM_DF(释放free掉的内存还是放在heap list里,方便以后找出这块内存的具体位置)。

_CrtMemCheckpoint() 设置内存检测点,类似于给当前heap内存做一个快照。快照信息就放在它的参数里面,如memStat里。

准备工作做完后,再次运行这个程序,heap 错误的提示又再次出现了,下面进行分析

红色圈起来的地方值得注意,一个是出问题的内存的位置,一个是出问题的内存的大小。

刚才提到了一个变量memStat,这是一个结构体变量,定义如下:

pBlockHeader是一个结构体指针,指向内存块链表

lCounts介绍了各种类型(_FREE_BLOCK、_NORMAL_BLOCK、_CRT_BLOCK、_IGNORE_BLOCK、_CLIENT_BLOCK)的内存块的数量,这些内存块可以通过遍历pBlockHeader指向的链表得到

其他的这里用不到,就不介绍了,详情参考 MSDN

_FREE_BLOCK 类型的内存块就是出问题的内存块,通过遍历pBlockHeader就可以找到,pBlockHeader类型定义如下

由以上定义可以看出来,pBlockHeader指向一个双向链表,其中

szFileName 是申请空间时的文件名

nLine 是申请时的代码行号

nDataSize 是申请的内存大小

nBlockUse 是内存块类型(_FREE_BLOCK、_NORMAL_BLOCK、_CLIENT_BLOCK等)

lRequest 是申请次数,查找内存泄漏的时候用的到

gap/anotherGap 是填充空间,做内存边界用,可用来检测上下溢出

data 这块就是我们使用的内存了,data的地址和出错时提示的地址是一个内容

通过定义,可以发现 _CrtMemBlockHeader 的大小是32即0x20,在pBlockHeader里查找错误地址时需要查找 [xxxx – 0x20] 这个地址。

在这个例子里,就是查找[0x00035C68 – 0x20 = 0x00035C48],在Watch里跟踪pBlockHeader,很快就可以找到这个地址

红色圈起来的地方就可以找到出问题的 heap 地址了

对照源代码

就能发现是哪个地方申请的变量出问题了

跟踪这个变量,一般很快就能发现问题了

demo下载:http://download.csdn.net/detail/xkxjy/3869116

 

 

posted on 2011-12-01 22:38  FlowingCloud  阅读(12030)  评论(0编辑  收藏  举报

导航