2

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

我应该怎么做才能在发生堆损坏的确切位置中断?

4

2 回答 2

1

启用 FULL pageheap 可以增加调试器在发生堆损坏时捕获它的机会:

gflags /p /enable /full <processname>

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

于 2011-07-20T19:54:33.140 回答
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% 保证在损坏发生的那一刻准确捕捉到损坏。您需要像PurifyValgrind这样的工具来跟踪每个内存访问。

别误会,我觉得Pageheap还是很有用的。与提到的PurifyValgrind相比,它导致的性能下降要少得多,因此它允许运行更复杂的场景。

于 2013-09-07T23:33:29.277 回答