VS2008 Включить исключение C ++ с SEH - PullRequest
2 голосов
/ 21 января 2011

Я не хочу, чтобы моя программа аварийно завершала работу, поэтому я включил исключение C ++ с помощью SEH. Так что, если есть какие-то ошибки, то есть происходит доступ по нулевому указателю, моя программа может перехватить его с помощью catch (...).

Я хочу знать: 1. Есть ли какой-либо недостаток включения исключения C ++ с SEH? 2. Как я могу узнать подробности исключения, когда оно перехватывается catch (...)?

1 Ответ

1 голос
/ 21 января 2011
  1. Насколько я знаю, недостатков в производительности нет, потому что я почти уверен, что исключения C ++ в любом случае реализованы через SEH.Все, что вы делаете, это позволяете расширению получать исключения на уровне ОС.Тем не менее, есть один существенный недостаток, затронутый в двух.

  2. Обычно вы используете __try и __except для отлова исключений SEH; больше информации здесь .Обратите внимание, что в этом и заключается недостаток: исключения, перехваченные таким образом, не запускают деструкторы.Однако вы можете использовать функцию _set_se_translator для перевода исключений SEH в исключения C ++.

Вот кое-что из одного из моих проектов, который делает это (использует Boost и C ++0x в 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);
}

Я вычеркнул несколько вещей, но вы поняли идею.Таким способом вы можете извлечь всю ту же информацию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...