一次堆破坏的调试经历

过程是这样的,在vc debug的过程中,突然弹出了一个assert窗口:

 

Windows has triggered a breakpoint in cs.exe.

This may be due to a corruption of the heap, which indicates a bug in cs.exe or any of the DLLs it has loaded.

This may also be due to the user pressing F12 while cs.exe has focus.

 

查看output输出:

Heap missing last entry in committed range near e664630

Windows has triggered a breakpoint in cs.exe.

 

This may be due to a corruption of the heap, which indicates a bug in cs.exe or any of the DLLs it has loaded.

 

不废话,直接查看该内存是什么:

0x0E664630  0e 00 0f 00 59 03 10 04 aa aa cd ab 00 10 72 85 38 00

看不出什么,往上再看看:

0x0E66460C  07 e2 04 00 a8 01 66 0e 01 00 cd cd fd fd fd fd....

 

看来这就是块堆内存,实在看不出什么,决定暂时忽略. 过了几天,该错误没有再出现过.

 

但就在交付程序前一天测试中,又出现了这个错误.看来一颗定时炸弹是埋藏在了程序中.必须找出来,否则后果很严重.

 

首先要做的就是要重现这个问题,如果每次碰巧遇到这个问题的话,实在无从下手.从症状来看,是个典型的Heap Corrupt.所以先使用工具:pageheap,以做到能够百分百重现那个堆破坏.

 

page heap工具启用的两种方法:Full-page heap和Normal page heap

我先使用了Normal page heap 命令为pageheap /enable xx.exe /normal

 

然后通过windbg设置符号表:x:/symbols_folder;srv*x:/symbols_folder*http://msdl.microsoft.com/download/symbols

 

开始各种调试,几乎用遍了<>这本书中指导的各种命令,(调试过程省略2000字)未果.几乎崩溃时,突然看到书上的这么一段话:

 

普通页堆通过填充模式检测堆块破坏,需要再发生堆破坏之后再调用一次堆管理器.

完全页堆除了特定的填充模式外,它还为每个堆块增加了防护页,防护页是一个页不可访问的内存,它被放置在堆块的起始位置和结束位置上.防止堆块上下溢出.

 

我靠,直接pageheap /enable xx.exe /full 设置完全页堆模式.重新运行程序.

瞬间程序崩掉,这个激动呀.还是第一次看见程序崩掉那么激动,查看崩溃的代码:

原来是把一个类指针强转为另一个子类的指针,调用了子类的一个函数,但是该类不存在这个函数.同时这个子类函数里面做了一次bool变量赋值,结果这个值就写到了堆地址里面去了.

 

总结

以后遇到类似问题,直接pageheap full 全开.

你可能感兴趣的:(c和c++)