在某些情况下,SetUnhandledExceptionFilter
(https://msdn.microsoft.com/en-us/library/windows/desktop/ms680634(v=vs.85).aspx)似乎对捕获致命错误没有帮助,我正在尝试改进异常诊断(更像是基本的崩溃处理)。这种情况是在关闭时,不同的atexit函数和单例析构函数等正在运行(清理)。同样令人担忧的是,析构函数将因noexcept声明不匹配而终止。
实际上,使用AddVectoredExceptionHandler
(https://msdn.microsoft.com/en-us/library/windows/desktop/ms679274(v=vs.85).aspx)似乎是一个不错的选择,因为它的功能更像是调试器的“第一次机会异常”,但是,它也因此被调用(太多)(以及正常的异常情况,某些信号等)。
答案 0 :(得分:1)
AddVectoredExceptionHandler
添加的VEH处理程序将在到达基于帧的处理程序之前处理异常。
由SetUnhandledExceptionFilter
设置的过滤器将在基于帧的处理程序失败后处理异常。
两种常规处理(例如try...except
或try...catch
)和信号处理程序都被实现为基于帧的处理程序,信号处理程序被实现为最后一个基于帧的处理程序。
在链解开之前,没有可靠的方法来区分致命和非致命异常。语言异常(代码0xE06D7363
),其他软件异常和硬件异常(例如代码0xC0000005
的访问冲突)都可能是致命的,也可能是致命的。
因此,AddVectoredExceptionHandler
几乎没有使用。除了set_terminate
,您还必须处理signal
,_set_invalid_parameter_handler
,SetUnhandledExceptionFilter
等。
您可以通过设置signal
来确保SIG_DFL
的处理程序退回到默认值,在这种情况下,它将回退到SetUnhandledExceptionFilter
设置的处理程序。
默认的_set_invalid_parameter_handler
不会故意退回到SetUnhandledExceptionFilter
设置的处理程序,但是如果您将传递给_set_invalid_parameter_handler
的函数设置为引发自己的SEH异常,它将退回到处理程序由SetUnhandledExceptionFilter
设置。
我不记得set_terminate
和其他人怎么了。您需要尝试一下。但是作为最后的选择,您可能总是会引发自己的SEH异常,使用__except捕获它,并传递给UnhandledExceptionFilter
,然后将调用您的SetUnhandledExceptionFilter
回调:
__try
{
RaiseException(0xE0000001,0,0,NULL);
}
__except(UnhandledExceptionFilter(GetExceptionInformation()))
{
}
答案 1 :(得分:0)
好吧,您可以做的是添加矢量化异常处理程序,但实际上不检查异常,而是将其存储在某个地方(将线程ID映射到异常信息的某些部分的映射)并安装终止处理程序-如果它将被调用,那么您知道映射中的异常之一就是错误的异常。为避免保留过多的数据,请在线程退出后添加线程本地raii类,该类将从映射中删除条目。当然,这会带来性能上的损失(在每次出现异常时都锁定地图),但是如果这确实是您想要的,那么这是一种有效的方法。
通用代码:
#include <exception>
#include <iostream>
#include <thread>
#include <Windows.h>
void termination_handler()
{
// Look at the map, you will not know which one caused it but at least have all of them
std::cout << "termination_handler called\n";
}
LONG VectoredExceptionHandler(_EXCEPTION_POINTERS *ExceptionInfo)
{
// Put exception record somewhere - e.g map of thread ids to to exception record, maybe symbols
return EXCEPTION_CONTINUE_SEARCH;
}
void foo()
{
throw std::exception();
}
int main(int argc, char** argv)
{
AddVectoredExceptionHandler(0, VectoredExceptionHandler);
std::set_terminate(termination_handler);
std::thread t(foo);
t.join();
return 0;
}