【问题标题】:VS2008 Enable C++ Exception with SEHVS2008 使用 SEH 启用 C++ 异常
【发布时间】:2011-01-21 02:25:08
【问题描述】:

我不希望我的程序崩溃,所以我使用 SEH 启用了 C++ 异常。因此,如果出现一些错误,即发生 NULL 指针访问,我的程序可以使用 catch(...) 捕获它。

我想知道: 1.用SEH启用C++异常有什么缺点吗? 2. 被catch(...)捕获的异常细节如何知道?

【问题讨论】:

    标签: visual-c++ exception exception-handling


    【解决方案1】:
    1. 据我所知,没有性能缺陷,因为我很确定 C++ 异常无论如何都是通过 SEH 实现的。您所做的只是使扩展程序也能够获取操作系统级别的异常。但是,有一个主要缺点,分为两点。

    2. 您通常使用__try__except 来捕获SEH 异常; more information here。请注意,这是缺点所在:以这种方式捕获的异常不会运行析构函数。但是,您可以使用函数_set_se_translator 将 SEH 异常转换为 C++ 异常。

    这是我的一个项目中的一些内容(在 MSVC 2010 中使用 Boost 和 C++0x):

    bool ignore_exception(unsigned pCode)
    {
        const unsigned ignoreList[] = {EXCEPTION_BREAKPOINT,
            EXCEPTION_FLT_DENORMAL_OPERAND, EXCEPTION_FLT_DIVIDE_BY_ZERO,
            EXCEPTION_FLT_INEXACT_RESULT, EXCEPTION_FLT_OVERFLOW, EXCEPTION_FLT_UNDERFLOW,
            EXCEPTION_INT_OVERFLOW, EXCEPTION_SINGLE_STEP};
    
        auto result = std::search_n(std::begin(ignoreList), std::end(ignoreList),
                        1, pCode);
        return result != std::end(ignoreList);              
    }
    
    std::string code_string(unsigned pCode)
    {
        switch (pCode)
        {
        case EXCEPTION_ACCESS_VIOLATION:
            return "Access violation";
        case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
            return "Out of array bounds";
        case EXCEPTION_BREAKPOINT:
            return "Breakpoint";
        case EXCEPTION_DATATYPE_MISALIGNMENT:
            return "Misaligned data";
        case EXCEPTION_FLT_DENORMAL_OPERAND:
            return "Denormalized floating-point value";
        case EXCEPTION_FLT_DIVIDE_BY_ZERO:
            return "Floating-point divide-by-zero";
        case EXCEPTION_FLT_INEXACT_RESULT:
            return "Inexact floating-point value";
        case EXCEPTION_FLT_INVALID_OPERATION:
            return "Invalid floating-point operation";
        case EXCEPTION_FLT_OVERFLOW:
            return "Floating-point overflow";
        case EXCEPTION_FLT_STACK_CHECK:
            return "Floating-point stack overflow";
        case EXCEPTION_FLT_UNDERFLOW:
            return "Floating-point underflow";
        case EXCEPTION_GUARD_PAGE:
            return "Page-guard access";
        case EXCEPTION_ILLEGAL_INSTRUCTION:
            return "Illegal instruction";
        case EXCEPTION_IN_PAGE_ERROR:
            return "Invalid page access";
        case EXCEPTION_INT_DIVIDE_BY_ZERO:
            return "Integer divide-by-zero";
        case EXCEPTION_INT_OVERFLOW:
            return "Integer overflow";
        case EXCEPTION_INVALID_DISPOSITION:
            return "Invalid exception dispatcher";
        case EXCEPTION_INVALID_HANDLE:
            return "Invalid handle";
        case EXCEPTION_NONCONTINUABLE_EXCEPTION:
            return "Non-continuable exception";
        case EXCEPTION_PRIV_INSTRUCTION:
            return "Invalid instruction";
        case EXCEPTION_SINGLE_STEP:
            return "Single instruction step";
        case EXCEPTION_STACK_OVERFLOW:
            return "Stack overflow";
        default:
            return "Unknown exception";
        }
    }
    
    void stack_fail_thread()
    {
        std::cerr << "Unhandled exception:\n"
                    << code_string(EXCEPTION_STACK_OVERFLOW) << '\n';
        std::cerr << "Terminating." << std::endl;
    
        // can print a stack dump of the failed
        // thread to see what went wrong, etc...
    
        std::exit(EXIT_FAILURE);
    }
    
    void exception_translator(unsigned pCode, _EXCEPTION_POINTERS*)
    {
        // minimize function calls if it's a stack overflow
        if (pCode == EXCEPTION_STACK_OVERFLOW)
        {
            // do some additional processing in another thread,
            // because the stack of this thread is gone
            boost::thread t(stack_fail_thread);
            t.join(); // will never exit
        }
        else if (!ignore_exception(pCode))               
        {
            // can add a stack dump to the exception message,
            // since these tend to be pretty severe, etc...
            BOOST_THROW_EXCEPTION(std::runtime_error(code_string(pCode)));
        }
    }
    
    void hook_signals()
    {
        _set_se_translator(exception_translator);
    }
    

    我删除了一些东西,但你明白了。您可以通过这种方式提取所有相同的信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-04
      • 1970-01-01
      • 1970-01-01
      • 2011-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多