2011-01-21 85 views
2

我不希望我的程序崩潰,所以我啓用了C++ Exception with SEH。所以,如果有一些錯誤,即NULL指針訪問發生,我的程序可以通過catch(...)來捕獲它。VS2008使用SEH啓用C++異常

我想知道: 1. SEH啓用C++異常有什麼缺點嗎? 2.如何通過catch(...)捕獲異常細節?

回答

1
  1. 據我所知,沒有性能缺陷,因爲我非常肯定C++異常是通過SEH實現的。你所做的只是讓擴展獲得操作系統級的異常。但是,有兩個主要的缺點,即觸及。

  2. 您通常使用__try__except來捕捉SEH異常; more information here。注意這是缺點的地方:以這種方式捕獲的異常不會運行析構函數。但是,您可以使用函數_set_se_translator將SEH異常轉換爲C++異常。

下面是從我的項目之一的東西做這個(使用升壓和C++ 0x中,2010年MSVC):

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

我剝幾件事情了,但你的想法。您可以通過這種方式提取所有相同的信息。