PageHeap没有显示确切的崩溃位置

时间:2011-05-08 03:47:11

标签: c++ memory-management windbg pageheap

我正在使用PageHeap来识别堆损坏。我的应用程序有堆损坏。但是,当应用程序为传递给方法的字符串创建stl对象时,应用程序会中断(由于崩溃)。我在碰撞位置附近看不到任何可见的内存问题。我启用了整页堆来检测堆损坏和/ RTC以防止堆栈损坏。

如何在发生堆损坏的确切位置打破?

2 个答案:

答案 0 :(得分:1)

启用FULL pageheap会增加调试器在发生堆时发生损坏的可能性:

gflags /p /enable /full <processname>

此外,如果您可以找到被覆盖的地址,您可以在windbg中设置内存访问的断点。不确定VS调试器是否具有相同的功能。

答案 1 :(得分:0)

Pageheap 并不总是在发生堆损坏时始终检测到它。

Pageheap 在分配后立即插入无效页面。因此,无论何时超出已分配的块,您都会获得AV。但还有其他可能的情况。一个例子是在分配的块破坏堆块头数据结构之前写入。堆块头是有效的可写内存(很可能与分配的块在同一页面中)。请考虑以下示例:

#include <stdlib.h>

int
main()
{
    void* block = malloc(100);
    int* intPtr = (int*)block;

    *(intPtr-1) = 0x12345; // no crash

    free(block); // crash

    return 0;
}

所以在分配的块之前写一些垃圾就好了。启用 Pageheap 后,示例会在free()调用内部中断。这是调用堆栈:

    verifier.dll!_VerifierStopMessage@40()  + 0x206 bytes   
    verifier.dll!_AVrfpDphReportCorruptedBlock@16()  + 0x239 bytes  
    verifier.dll!_AVrfpDphCheckNormalHeapBlock@16()  + 0x11a bytes  
    verifier.dll!_AVrfpDphNormalHeapFree@16()  + 0x22 bytes 
    verifier.dll!_AVrfDebugPageHeapFree@12()  + 0xe3 bytes  
    ntdll.dll!_RtlDebugFreeHeap@12()  + 0x2f bytes  
    ntdll.dll!@RtlpFreeHeap@16()  + 0x36919 bytes   
    ntdll.dll!_RtlFreeHeap@12()  + 0x722 bytes  
    heapripper.exe!free(void * pBlock=0x0603bf98)  Line 110 C
>   heapripper.exe!main()  Line 11 + 0x9 bytes  C++
    heapripper.exe!__tmainCRTStartup()  Line 266 + 0x12 bytes   C
    kernel32.dll!@BaseThreadInitThunk@12()  + 0xe bytes 
    ntdll.dll!___RtlUserThreadStart@8()  + 0x27 bytes   
    ntdll.dll!__RtlUserThreadStart@8()  + 0x1b bytes    

Pageheap 启用严格的堆一致性检查,但检查不会启动,直到调用其他一些堆API。在堆栈上可以看到检查例程。 (如果没有 Pageheap ,应用程序可能只是在堆实现中尝试使用无效指针的AV。)

因此, Pageheap 并不能100%保证在发生损坏时准确捕获损坏。您需要跟踪每次内存访问的 Purify Valgrind 等工具。

不要误解我的意思,我认为 Pageheap 仍然非常有用。与上面提到的 Purify Valgrind 相比,它导致性能降低更少,因此它允许运行更复杂的场景。