2011-01-21 2 views
2

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

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

ответ

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

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

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

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