过滤关键/致命例外,以与AddVectoredExceptionHandler一起使用

Filtering critical/fatal exceptions for use with AddVectoredExceptionHandler

本文关键字:以与 AddVectoredExceptionHandler 一起 过滤      更新时间:2023-10-16

在某些情况下,在SetUnhandledExceptionFilter(https://msdn.microsoft.com/en-us/library/library/windows/desktop/mss680634)(v = vs.85).aspx)似乎无助于捕获致命错误。情况是在关闭和不同的Abexit功能和单顿驱动器等时进行运行(清理)。同样,由于不匹配的NOExcept声明,驱灾者将终止的情况也引起了人们的关注。

使用AddVectoredExceptionHandler(https://msdn.microsoft.com/en-us/library/windows/desktop/ms679274(v=vs.85).aspx)确实是一个很好的选择,因为它更像是一个很好的选择但是,调试者的"第一个机会例外",但是它也会被调用(方式)太多(也是普通例外,一些信号等)。

  1. 理想情况下,将有一种方法来判断异常是否
    将被处理或结果为终止。
  2. 异常代码是过滤的另一种方法 - 使用CPP富有的投掷异常代码显然应该继续 - 我觉得它会太多的锅炉或试用以及获取"正确"(致命的)异常代码进行过滤的错误。

AddVectoredExceptionHandler添加的车辆处理程序在达到基于框架的处理程序之前将处理异常。

SetUnhandledExceptionFilter设置的过滤器将在基于帧的处理程序失败后处理异常。

正常处理(例如try...excepttry...catch)和信号处理程序都是基于框架的操作者,信号操作者作为基于框架的最后一个基于框架的处理程序的实现。

没有可靠的方法来区分致命非致命例外,直到链条解开为止。语言异常(代码0xE06D7363),其他软件异常和硬件异常(例如使用代码0xC0000005访问违规) - 所有这些都可能是致命的和非致命的。

因此,AddVectoredExceptionHandler几乎不使用。除SetUnhandledExceptionFilter外,您还必须处理set_terminatesignal_set_invalid_parameter_handler等。

您可以确保signal的处理程序通过设置SIG_DFL降回默认值,在这种情况下,它将由SetUnhandledExceptionFilter设置为Handler。

默认的_set_invalid_parameter_handler故意不会落到SetUnhandledExceptionFilter设置的Handler上,但是如果将功能设置为传递给_set_invalid_parameter_handler以提高您自己的SEH例外,它将落后于SetUnhandledExceptionFilter设置的Handler。

我不记得set_terminate等是什么。您需要对此进行实验。但是,作为最后的手段,您可能总是会提高自己的SEH例外,以__Except抓住它,然后传递给UnhandledExceptionFilter,然后您的SetUnhandledExceptionFilter回调将被调用:

__try
{
     RaiseException(0xE0000001,0,0,NULL);
}
__except(UnhandledExceptionFilter(GetExceptionInformation()))
{
}

好吧,您可以做的是添加矢量化的异常处理程序,但实际上没有检查那里的异常,而是将任何一个存储在某个地方)并安装终止处理程序 - 如果被称为,那么您知道地图中的一个例外之一是错误的。为避免保留多余的数据,请在线程退出后,添加一个线程本地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 calledn";
}
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;
}