C++ 筛选与AddVectoredExceptionHandler一起使用的关键/致命异常
我正在尝试改进异常诊断(更像是基本的崩溃处理),以便在某些情况下C++ 筛选与AddVectoredExceptionHandler一起使用的关键/致命异常,c++,visual-c++,exception-handling,c++17,terminate,C++,Visual C++,Exception Handling,C++17,Terminate,我正在尝试改进异常诊断(更像是基本的崩溃处理),以便在某些情况下SetUnhandledExceptionFilter()似乎无法帮助捕获致命错误。这种情况是在关闭时,不同的atexit函数和单例析构函数等正在运行(清理)。另外,由于noexcept声明不匹配,析构函数将终止的情况也值得关注 使用AddVectoredExceptionHandler()确实是一个不错的选择,因为它的功能更像是调试器的第一次机会异常,但是它也因此在太多的情况下被调用(同样是正常异常、某些信号等) 理想情况下,会有
SetUnhandledExceptionFilter
()似乎无法帮助捕获致命错误。这种情况是在关闭时,不同的atexit函数和单例析构函数等正在运行(清理)。另外,由于noexcept声明不匹配,析构函数将终止的情况也值得关注
使用AddVectoredExceptionHandler
()确实是一个不错的选择,因为它的功能更像是调试器的第一次机会异常,但是它也因此在太多的情况下被调用(同样是正常异常、某些信号等)
将被处理,或者如果结果调用terminate
好的,您可以做的是添加向量化异常处理程序,但不在那里实际检查异常,而是将其存储在某个位置(将线程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;
}
#包括
#包括
#包括
#包括
无效终止\u处理程序()
{
//看看地图,你不知道是哪一个导致了它,但至少有所有的原因
std::coutVEH处理程序由addvectoredceptionhandler
添加,将在异常到达基于帧的处理程序之前处理异常
由SetUnhandledExceptionFilter设置的筛选器将在基于帧的处理程序失败后处理异常
正常处理(如try…except
或try…catch
)和信号处理程序都实现为基于帧的处理程序,信号处理程序实现为最后一个基于帧的处理程序
在解开链之前,没有可靠的方法来区分致命异常和非致命异常。语言异常(代码0xE06D7363
),其他软件异常和硬件异常(如代码0xC0000005
)都可能是致命和非致命的
因此,AddVectoredExceptionHandler
几乎没有用处。除了SetUnhandledExceptionFilter
之外,还必须处理set\u terminate
、signal
、set\u invalid\u parameter\u handler
等
您可以通过设置SIG_DFL
,确保信号的处理程序返回到默认值,在这种情况下,它将返回到SetUnhandledExceptionFilter
设置的处理程序
默认的\u set\u invalid\u parameter\u handler
故意不返回到SetUnhandledExceptionFilter
设置的处理程序,但如果将函数设置为\u set\u invalid\u parameter\u handler
以引发自己的SEH异常,它将返回到SetUnhandledExceptionFilter
设置的处理程序
我不记得SetUnhandledExceptionFilter
和其他的方法是什么。你需要尝试一下。但是作为最后的手段,你可以总是提出你自己的SEH异常,用uuxception捕捉它,然后传递到UnhandledExceptionFilter
,然后你的SetUnhandledExceptionFilter
回调将被调用:
__try
{
RaiseException(0xE0000001,0,0,NULL);
}
__except(UnhandledExceptionFilter(GetExceptionInformation()))
{
}
您的回答非常好,但我希望缺少simpel解决方案。set_terminate等将是一个很好的替代方案-如果调用terminate处理程序时堆栈中有趣的部分还没有解开的话。我还发现,仅异常是不够的-因为您有引发用户类型的异常,例如,throw std::bad_alloc{}
。当程序退出时,可以在析构函数内抛出此异常。下面是一个解决方案,其中有一个示例,说明如何注册所有其他异常类型,即中止等: