过滤关键/致命异常以与AddVectoredExceptionHandler一起使用

问题描述 投票:1回答:2

我正在尝试改进异常诊断(更像是基本的崩溃处理),因为某些情况下SetUnhandledExceptionFilterhttps://msdn.microsoft.com/en-us/library/windows/desktop/ms680634(v=vs.85).aspx)似乎没有帮助捕获致命错误。这种情况是在关闭时运行不同的atexit函数和单例析构函数等(清理)。另外,由于noexcept声明不匹配而导致析构函数终止的情况也是一个问题。

确实使用AddVectoredExceptionHandlerhttps://msdn.microsoft.com/en-us/library/windows/desktop/ms679274(v=vs.85).aspx)似乎是一个很好的选择,因为它的功能更像是调试器的“第一次机会异常”,但它也因此被调用(方式)太多的情况(也是正常异常,某些信号等)。

  1. 理想情况下,会有某种方式来判断异常是否存在 将被处理或终止被作为结果被调用。
  2. 异常代码是另一种过滤方式 - 使用cpp基因处理抛出异常代码,很明显它应该继续 - 我有一种感觉,它会过多地进行样板或试错,以获得'正确'(致命)要过滤的例外代码。
c++ visual-c++ exception-handling c++17 terminate
2个回答
1
投票

AddVectoredExceptionHandler添加的VEH处理程序将在它们到达基于帧的处理程序之前处理异常。

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

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

在链条解开之前,没有可靠的方法来区分致命和非致命异常。语言异常(代码0xE06D7363),其他软件异常和硬件异常(如代码0xC0000005的访问冲突) - 都可能是致命的而且是非致命的。

因此,AddVectoredExceptionHandler很难使用。除了set_terminate之外,你还必须处理signal_set_invalid_parameter_handlerSetUnhandledExceptionFilter等。

您可以通过设置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()))
{
}

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;
}
© www.soinside.com 2019 - 2024. All rights reserved.