通常情况下堆被破坏(比如写越界或者多次释放堆内存)程序是不会立即崩溃的,导致抓不到堆被破坏的第一现场造成排查问题很困难。
比如下面这个问题场景:
如图一,设置windbg为默认调试器,程序每次抛异常抓到的调用栈显示都是在分配堆内存时抛出的,但是抛出异常的位置不固定,由于堆被破坏的第一现场已经丢失,通过调试器很难找到出问题的具体位置。
通过网上查找资料,使用pageheap.exe进行了问题的排查,效果很好,如图二,每次调用栈都位于同样的位置,每次出现堆堆的异常访问都会产生违规内存访问,这样很容易就能定位问题所在。
这个工具的实现原理是在每块分配的堆内存后面的内存页属性都设置为不可访问属性,释放掉的堆内存也设置为不可访问属性,这样发生堆违规访问(比如越界或者使用已释放过的堆内存)都会导致违规内存访问,这样就能在第一时间定位问题所在。
pageheap.exe使用方法是在cmd里输入pageheap.exe /enable 可执行文件名,如图三,
(图一)
(图二)