开发者

VS2008 Enable C++ Exception with SEH

I don't want my program to crash, so i enabled C++ Exception with SEH. So that, if there's some errors i.e. NULL pointer access happens, my program can catch it with catch(...).

I want to known: 1. Is there any drawback of enable C++ exception with SEH? 2. How can i know exception details when it is catched b开发者_Python百科y catch(...)?


  1. As far as I know, there are no performance drawbacks, because I'm pretty sure C++ exceptions are implemented via SEH anyway. All you're doing is enabling the extension to get OS-level exceptions as well. However, there is one major drawback, touched on in two.

  2. You normally use __try and __except to catch SEH exceptions; more information here. Note this is where the drawback is: exceptions caught this way do not run destructors. However, what you can do is use the function _set_se_translator to translate SEH exceptions into C++ exceptions.

Here's something from one of my projects that does this (uses Boost and C++0x in MSVC 2010):

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);
}

I stripped several things out, but you get the idea. You can extract all the same information this way.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜