堆调试利器-Pageheap

     刚刚花了一个星期磨出一来一个Planet的*.prj类型的一周项目,感觉收获很大,特此作出分享.

     此项目是要解决一个Heap Corruption的问题,但是我们知道,通常情况下,当我们在堆中分配了一段内存,尽管在使用过程中可能出现了越界操作,但是系统在越界的一瞬间常常并不直接报错,而是在最后delete 时抛出一个Heap Corruption。这是因为操作系统的堆分配粒度是一个4k,若内存越界不是刚好在那个4k边界上,并不会引起操作系统的警觉而报错。

   如果我们只是在Heap Corruption发生的时候察看call stack,会发现得不到多少有用的信息。在一份规模较大的代码中手工检查也

不是很现实。

这个时候,堆调试利器-PageHeap可以帮上大忙.此工具可以强迫程序在把每一块堆都分配在一个4k内存页的末尾位置,并标记下一块4k

紧邻内存为不可用,一旦越界,马上报错。但是当我一开始写下如下的代码进行测试时,却发现代码仍是在直到delete 时才报错:

 

char *pcTest = new char[10];

pcTest [10] = 1;

//...

//...

//...

delete []pcTest;

 

打开代码一看,当进行了new操作后,在debug模式下内存中实际

情况如下:

0x0342AFF0  cd cd cd cd cd cd cd cd

0x0342AFF8  cd cd fd fd fd fd d0 d0

下一块4k:   ?? ?? ?? ?? ?? ?? ?? ??

10个cd是可使用的内存区,4个fd是debug模式下用来debug的,两个d0起占位的作用。因为内存分配的首地址必须是8的倍数,所以尽管pageheap尽量的把新分配的内存分配在4k末尾,但刚出界时是写在了那几个fd和d0上,并没有超越4k界。

若换作pcTest[16] = 1时,系统才认为是非法操作。综上所述,即使是用了pageheap,在某些情况下仍不能立即定位出错点.但大多数情况下还是很好用滴。

 

附:

 

那几个fd是debug模式下用来debug的,如前所说,操作系统级的排查只能查出在4k界上的溢出,但是在debug模式下,如果那4个fd在delete时发现被改过了,也会报错,也就是说,以下代码会在delete时,发现4个fd被改过而报错:

    char *pCTest = new char[1];

    pCTest[4] = 1;

    delete   []pCTest;

但是,下面这份由于是改动了d0,却一切正常:

    char *pCTest = new char[1];

    pCTest[5] = 1;

    delete []pCTest;

 

那几个d0的出现应该是由于字节对齐的问题,我的环境下好像不论啥类型的都是以8字节对齐,囧...

如果是在release模式下,fd和d0都不会出现,也就不会有溢出检查了。所以下面的代码会在debug模式下报错,而release下正常:

    char *pCTest = new char[1];

    pCTest[4] = 1;

    delete []pCTest;

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值