Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 筛选与AddVectoredExceptionHandler一起使用的关键/致命异常_C++_Visual C++_Exception Handling_C++17_Terminate - Fatal编程技术网

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
  • 异常代码是另一种过滤方法-使用cpp Generated抛出异常代码,显然它应该继续- 我有一种感觉,这将是太多的陈词滥调或审判 获取要筛选的“正确”(致命)异常代码时出错

  • 好的,您可以做的是添加向量化异常处理程序,但不在那里实际检查异常,而是将其存储在某个位置(将线程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{}
    。当程序退出时,可以在析构函数内抛出此异常。下面是一个解决方案,其中有一个示例,说明如何注册所有其他异常类型,即中止等: