我遇到了一个问题,即传递给SetUnhandledExceptionFilter的函数在exception代码c0000374提升时没有被调用。 但它可以正常工作,例外代码为c0000005。 然后,我尝试使用AddVectoredExceptionHandler ,而没有问题,处理函数被调用正确。
这是API错误? 我可以在任何地方使用AddVectoredExceptionHandler而不是SetUnhandledExceptionFilter吗?
这两个函数正常工作
// Exception code c0000005 int* p1 = NULL; *p1 = 99;
只有AddVectoredExceptionHandler可以捕获这个exception。 (为了certificate它不依赖于运行时库,我手动引发exception,结果相同。)
// Exception code c0000374 RaiseException(0xc0000374, 0, 0, NULL);
testing程序。
#include <tchar.h> #include <fstream> #include <Windows.h> LONG WINAPI VectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) { std::ofstream f; f.open("VectoredExceptionHandler.txt", std::ios::out | std::ios::trunc); f << std::hex << pExceptionInfo->ExceptionRecord->ExceptionCode << std::endl; f.close(); return EXCEPTION_CONTINUE_SEARCH; } LONG WINAPI TopLevelExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) { std::ofstream f; f.open("TopLevelExceptionHandler.txt", std::ios::out | std::ios::trunc); f << std::hex << pExceptionInfo->ExceptionRecord->ExceptionCode << std::endl; f.close(); return EXCEPTION_CONTINUE_SEARCH; } int _tmain(int argc, _TCHAR* argv[]) { AddVectoredExceptionHandler(1, VectoredExceptionHandler); SetUnhandledExceptionFilter(TopLevelExceptionHandler); // Exception code c0000374 RaiseException(0xc0000374, 0, 0, NULL); // Exception code c0000005 // int* p1 = NULL; // *p1 = 99; return 0; }
它发生在MSVC CRT启动这个代码:
/* * Enable app termination when heap corruption is detected on * Windows Vista and above. This is a no-op on down-level OS's * and enabled by default for 64-bit processes. */ if (!_NoHeapEnableTerminationOnCorruption) { HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); }
如果你想禁用它( 不推荐),把nohetoc.obj
链接到你的程序。
实际上,在检测到堆损坏后,实际上直接在源代码中RtlReportCriticalFailure
,在堆管理器中调用RtlReportCriticalFailure
。 在这个函数中注册的SEH处理程序调用RtlReportException
,紧接着是NtTerminateProcess
。
我只能得出这样的结论:SEH处理程序是故意避免的 – 堆被破坏,堆栈内容(因此SEH注册)也被怀疑; 无论如何,应用程序无法从堆损坏中合理地恢复。