PageHeap 不显示确切的崩溃位置

发布于 2024-11-05 09:35:04 字数 179 浏览 3 评论 0原文

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

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

I am using PageHeap to identify heap corruption. My application has a heap corruption. But the application breaks(due to crash) when it creates an stl object for a string passed to a method. I cannot see any visible memory issues near the crash location. I enabled full page heap for detecting heap corruption and /RTCs for detcting stack corruption.

What should I do to break at the exact location where the heap corruption occurs?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

荒岛晴空 2024-11-12 09:35:04

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

gflags /p /enable /full <processname>

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

Enabling FULL pageheap can increase the chances of the debugger catching a heap corruption as it's happening:

gflags /p /enable /full <processname>

Also, if you can find out what address is getting overwritten, you can set up a breakpoint on memory access in windbg. Not sure if the VS debugger has the same feature.

会傲 2024-11-12 09:35:04

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,应用程序可能只是在堆实现中尝试使用无效指针。)

因此,Pageheap 并不能 100% 保证您准确地捕获损坏当它发生的那一刻。您需要像PurifyValgrind这样的工具来跟踪每次内存访问。

不要误会我的意思,我认为Pageheap仍然非常有用。与提到的 Purify 和 Valgrind 相比,它造成的性能下降要少得多,因此它允许运行更复杂的场景。

Pageheap does not always detect heap corruption exactly at the moment when it occurs.

Pageheap inserts an invalid page right after allocations. So whenever you overrun an allocated block you get an AV. But there are other possible cases. One example is writing just before an allocated block corrupting heap block header data structure. Heap block header is a valid writable memory (most likely in the same page with the allocated block). Consider the following example:

#include <stdlib.h>

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

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

    free(block); // crash

    return 0;
}

So writing some garbage just before the allocated block passes just fine. With Pageheap enabled the example breaks inside free() call. Here is the call stack:

    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 enables rigorous heap consistency checks, but the checks do not kick in untill some other heap API is called. The check routines are seen on stack. (Without Pageheap the application would probably just AV in heap implementation attempting to use an invalid pointer.)

So Pageheap does not give you 100% guarantee to catch a corruption exactly at the moment when it occurs. You need tools like Purify or Valgrind that track every memory access.

Don't get me wrong, I think Pageheap is still very useful. It causes much less performance degradation compared to the mentioned Purify and Valgrind, so it allows running much more complex scenarios.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文