使用Windbg在XP下Heap追踪失败的原因

1、故事背景
     最近同事的代码中碰到一个bug会导致奔溃的bug,从dump上看是由于某个对象的堆内存指针被释放了,但代码仍调用了该对象指针的虚函数,从而引起内存访问违法崩溃,由于该类被大量使用,无法直接定位到具体哪个类被提前释放了,从而打算开启堆页检查,跟踪该对象堆内存指针被释放的代码位置,从而揪出元凶。
     由于此bug在win7的机器上不易重现,在xp sp3的机器上较容易重现,故准备在xp sp3的机器上开启堆页检查(DHP),跟踪该对象指针被释放的代码位置和时机,由于未从用过gflag进行堆页检查和调试,故先写了段小代码练练手:
使用Windbg在XP下Heap追踪失败的原因

用gflag开启堆页检查:
使用Windbg在XP下Heap追踪失败的原因
    设好符号文件后祭出 Windbg 走起,崩溃触发后断下,输入 !heap -p -a ecx 指令一举揪出元凶,但现实却是如此的骨感:

004010d9 8b11            mov     edx,dword ptr [ecx]  ds:0023:0161cff0=????????

0:000> !heap -p -a ecx

ReadMemory error for address eeddccee

Use `!address eeddccee' to check validity of the address.

注:此处 ecx = pCTest

"mov     edx,dword ptr [ecx]"表示取虚表指针

Windbg提示的读取内存错误,且改地址的内容无法显示,查看下该内存地址属性:

0:000> !address ecx

    015d0000 : 0161b000 - 000b5000

                    Type     00020000 MEM_PRIVATE

                    Protect  00000001 PAGE_NOACCESS

                    State    00001000 MEM_COMMIT

                    Usage    RegionUsagePageHeap

                    Handle   015d1000

address命令正确的指示了该地址为私有堆内存,但该内存页不可访问。
     难道是堆页开启不正确?检查注册表:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options,确定已经正确的设置了,尝试其他多种设置,甚至换工具进行设置,但结依然如此。难道是机器问题?于是在win7 32位机器上重复上述过程,发现是可以正确的打印出堆内存指针被释放的栈回溯的:
使用Windbg在XP下Heap追踪失败的原因
     但更换其他xp机器依然不能正确显示。百度搜索无果,仔细看glfag使用说明和各项设置文档也无果,最后去翻了翻 Windows 调试的权威书《软件调试》关于页堆的章节,并按照该书666页查找栈回溯数据库的方法查了下所有UST数据库的回溯记录,找到了"CTEST* pCTest = new CTEST(); "的栈回溯几率,即申请堆内存的记录,但始终未找到释放堆内存的记录。于是再次怀疑xp下的页堆并没有真正启动或启动是有问题的,于是检查下页堆启动情况:
使用Windbg在XP下Heap追踪失败的原因
    惊现“ReadMemory error for address eeddccee”,且只展示一个Page Heap句柄了,剩下的未展示完全,但页堆明明白白的现实已经开启,也有了准页堆,但数据却显示不出来,说明数据可能被破坏,但测试代码如此简单,而且也被windbg第一时间断下,不可能去破坏数据,难道是Windbg读取有问题?于是再次对此疑问进行google,果然有个外国朋友也碰到了类似的问题,其在帖子中提出换成6.6.0007.5版即可解决,试了下果然在xp下顺利输出了用户态栈回溯。那么为什么高版本的Windbg会出现此问题呢?
     我想起在查找UST数据结构的时候,发现和《软件调试》上写的不一致,当时疑惑了下没有在意,再次翻出来对比发现:
使用Windbg在XP下Heap追踪失败的原因

Win7下StackTraceDataBase结构

使用Windbg在XP下Heap追踪失败的原因

XP下StackTraceDataBase结构

Win7下的 _STACK_TRACE_DATABASE 结构和xp下并不完全相同,关键的 Buckets(栈回溯记录)的结构偏移改了,而且原xp下是个数组,但win7下却变成了链表,故猜测高版本的Windbg在xp下依然使用了win7下的某些数据结构,从而导致Windbg解析出了问题,不知道算不算微软的bug。

由于低版本的Windbg已经很难找到了,故这里也放出我找到的6.6.0007.5版:
Widnbg6.6.0007.5.exe

上一篇:MySQL 连接方式


下一篇:Redis学习手册(事务)