我正在使用PageHeap来识别堆损坏。我的应用程序有堆损坏。但是,当应用程序为传递给方法的字符串创建stl对象时,应用程序会中断(由于崩溃)。我在碰撞位置附近看不到任何可见的内存问题。我启用了整页堆来检测堆损坏和/ RTC以防止堆栈损坏。
如何在发生堆损坏的确切位置打破?
答案 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 相比,它导致性能降低更少,因此它允许运行更复杂的场景。