[英]How to use std::set_terminate with SetUnhandledExceptionFilter?
有什么方法可以让我获得未捕获的 C++ 异常的.what()
,同时还安装了 Windows 未处理的异常过滤器?
为了演示,以下程序...
#include <windows.h>
#include <iostream>
static LONG WINAPI WindowsExceptionHandler(LPEXCEPTION_POINTERS ep) {
std::cerr << "FOO" << std::endl;
return EXCEPTION_EXECUTE_HANDLER;
}
void TerminateHandler() {
std::exception_ptr exception_ptr = std::current_exception();
try {
if (exception_ptr) std::rethrow_exception(exception_ptr);
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
}
int main() {
SetUnhandledExceptionFilter(WindowsExceptionHandler);
std::set_terminate(TerminateHandler);
throw std::runtime_error("BAR");
}
输出:
FOO
我希望它输出BAR
或FOOBAR
注释掉SetUnhandledExceptionFilter
使其工作(但这是不可接受的,因为它不会捕获其他 Windows 异常类型)。
显然SetUnhandledExceptionFilter
以某种方式覆盖了std::set_terminate
?
所有 C++ 异常内部都使用throw关键字。 内部它使用_CxxThrowException
和这个 api 调用RaiseException
函数与0xE06D7363
就地dwExceptionCode 。 因此,如果要使用TerminateHandler
处理它,则需要调用SetUnhandledExceptionFilter
为 C++ 异常返回的先前异常过滤器。
g_prevlpTopLevelExceptionFilter = SetUnhandledExceptionFilter(WindowsExceptionHandler);
和
if (ExceptionRecord->ExceptionCode == 0xE06D7363) {
return g_prevlpTopLevelExceptionFilter(ep);
}
LPTOP_LEVEL_EXCEPTION_FILTER g_prevlpTopLevelExceptionFilter;
LONG WINAPI WindowsExceptionHandler(LPEXCEPTION_POINTERS ep) {
PEXCEPTION_RECORD ExceptionRecord = ep->ExceptionRecord;
printf("%s: %x at %p", __FUNCTION__,
ExceptionRecord->ExceptionCode, ExceptionRecord->ExceptionAddress);
if (ULONG NumberParameters = ExceptionRecord->NumberParameters)
{
printf(" { ");
PULONG_PTR ExceptionInformation = ExceptionRecord->ExceptionInformation;
do
{
printf(" %p", (void*)*ExceptionInformation++);
} while (--NumberParameters);
printf(" } ");
}
printf("\n");
if (ExceptionRecord->ExceptionCode == 0xE06D7363) {
return g_prevlpTopLevelExceptionFilter(ep);
}
return EXCEPTION_EXECUTE_HANDLER;
}
void TerminateHandler() {
MessageBoxW(0, 0, __FUNCTIONW__, MB_ICONWARNING);
exit(-1);
}
void main() {
g_prevlpTopLevelExceptionFilter =
SetUnhandledExceptionFilter(WindowsExceptionHandler);
set_terminate(TerminateHandler);
throw "888";
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.