c – 修剪延迟的空闲队列时堆损坏

我目前正试图在我们的代码库中追踪堆损坏的来源,当打开完整页堆跟踪时(这只是正常的页面跟踪),它不会出现.

我正在使用Application Verifier打破损坏,并获得一个不太有用的停止代码00000008:

APPLICATION_VERIFIER_HEAPS_CORRUPTED_HEAP_BLOCK (8)
Corrupted heap block.
This is a generic error issued if the corruption in the heap block cannot be placed in a more specific category.

=======================================
VERIFIER STOP 00000008: pid 0xD30: Corrupted heap block.

00000000 : Heap handle used in the call.
0861C000 : Heap block involved in the operation.
0000043C : Size of the heap block.
00000000 : Reserved

=======================================

我不得不削减报告以保护无辜,但请忍受我. callstack显示:

1000c540 00000008 00000000 vrfcore!VerifierStopMessageEx+0x543
00000008 7c969624 00000000 vrfcore!VfCoreRedirectedStopMessage+0x81
00000000 00000009 0861c000 ntdll!RtlpDphReportCorruptedBlock+0x101
04a680ee 01001002 03ce1000 ntdll!RtlpDphTrimDelayedFreeQueue+0x84
03ce1000 01001002 04a680ee ntdll!RtlpDphNormalHeapFree+0xc0
03ce0000 01001002 137a0040 ntdll!RtlpDebugPageHeapFree+0x79
03ce0000 01001002 137a0040 ntdll!RtlDebugFreeHeap+0x2c
03ce0000 01001002 137a0040 ntdll!RtlFreeHeapSlowly+0x37
03ce0000 00000000 137a0040 ntdll!RtlFreeHeap+0xf9
137a0040 137a0040 030dfe61 msvcrt!free+0xc3

最初,我把注意力集中在对free()的调用上,假设我试图释放的内存是堆损坏的罪魁祸首.情况可能仍然如此,但我不再相信.当我逐步执行删除调用时,看着0x137a0040,通过调用RtlpDphNormalHeapFree()可以正确释放内存.我总结说它被正确释放,因为从0x137a0040到它的上限的内存大约76mb后来仅由f0组成,将here定义为free’d内存.

因此,在调用RtlpDphReportCorruptedBlock(),RtlpDphTrimDelayedFreeQueue()之前,我的注意力转向了调用.传递给RtlpDphReportCorruptedBlock()的参数会向我(只是一个猜测,我找不到关于这些函数的声明的任何提示)作为腐败的块.调查此块显示以下内容:

0861c000 f0 f0 f0 f0 4f f0 f0 f0 f0 f0 f0 f0 f0 f0 f0 f0 f0 f0 f0 …. O …………..

为什么这个第5个字节是4f,而所有其他的都是f0(已经被释放)? RtlpDphTrimDelayedFreeQueue()做什么?问题(如果这是问题)是这个函数试图释放显然已经释放的内存,或者这个函数是否期望这个内存已经空闲,并且在遇到第5个字节时正在丢失情节?

(第5个字节是唯一的奇数,0x0861c000到0x0861c43c是f0)

不幸的是,虽然我可以在100%的时间内重现堆损坏,但每次在其上放​​置数据断点时,地址似乎都会发生变化.

我在Windows XP SP3上运行,应用程序是用VC 6编写的

有任何想法吗?

最佳答案 这表明你在释放它之后修改了块 – 可能来自不同的线程,或者因为某些东西仍有指向它的指针. (当你释放它时,运行时将它设置为所有F0,保持一段时间,然后检查它仍然是所有F0;它不是,所以它必须在空闲后被修改.)

如果损坏位于块中的常量偏移量,则可以在调用free()的位置更改该位置的断点.

点赞