2010-08-19 99 views
7

有沒有人知道一個函數將從GetExceptionInformation()返回的EXCEPTION_POINTERS結構轉換爲可記錄的字符串?是否有一個函數將EXCEPTION_POINTERS結構轉換爲字符串?

如果它已經完成,我不想滾動我自己的。

編輯:基本上,我已經添加__try {} __except(){}塊來幫助應用程序在關鍵錯誤上優雅地失敗。雖然我在此,但我試圖儘可能詳細地記錄錯誤消息,以找到需要我們解決的問題。理想情況下,我想打印出文件名並將其排除在外,但我懷疑這是可能的,所以我希望能夠拋棄所有的異常信息,希望我們能夠儘可能接近找出問題的確切原因。

回答

4

沒有這樣的功能,因爲你需要私人符號來寫任何有意義的東西。 dbghelp.dll幫助解決了這個問題(特別是StackWalk function及其64位版本)

你想從異常記錄中取出什麼來放入日誌?只是例外代碼?寄存器上下文?堆棧回溯?

編輯:此外,如果你只是做什麼,但註冊Windows Error Reporting,你可以使用微軟的真棒服務,並得到了崩潰轉儲回人氣時段的。如果可以的話,這是記錄故障轉儲的最佳方法。

2

From here.

#include <windows.h> 
#include <iostream> 
#include <string.h> 
#include <eh.h> 
using namespace std; 

static void translateSEH(unsigned int u, EXCEPTION_POINTERS* pExcept) { 
    // Translate SEH exception to a C++ exception. NOTE: compiling with /EHa is required!! 
    static char msg[256]; 
    sprintf_s(msg, 256, "Unhandled exception 0x%08x at 0x%08x", 
    pExcept->ExceptionRecord->ExceptionCode, 
    pExcept->ExceptionRecord->ExceptionAddress); 
    throw exception(msg); 
} 

int main(){ 
    _set_se_translator(translateSEH); 
    int p = 0; 
    try { 
     cout<<1/p<<endl; 
    } 
    catch (std::exception& ex) { 
     cout << ex.what() << endl; 
    } 
} 
+3

我認爲* *剛纔的代碼和地址是不是特別有用,尤其是ASLR在Vista/Win7上,因爲您沒有記錄模塊基址 – 2010-08-19 18:57:46

2

沒有太多吧,你只是有興趣在異常代碼和地址。如果異常是EXCEPTION_ACCESS_VIOLATION,那麼您還需要轉儲前兩個ExceptionInformation值。第一個表示操作(0 =讀,1 =寫,8 =防止數據執行),第二個給出故障地址。

+1

除了0和1之外,還有8個「如果此值爲8,則線程會導致用戶模式數據執行預防(DEP)違規。從「EXCEPTION_RECORD結構」http://msdn.microsoft.com/en-us/library/windows/desktop/aa363082(v=vs.85).aspx – 2011-10-21 11:51:07

11
// Compile with /EHa 
#include <windows.h> 
#include <eh.h> 
#include <Psapi.h> 
#include <string> 
#include <sstream> 

class InfoFromSE 
{ 
public: 
    typedef unsigned int exception_code_t; 

    static const char* opDescription(const ULONG opcode) 
    { 
     switch(opcode) { 
     case 0: return "read"; 
     case 1: return "write"; 
     case 8: return "user-mode data execution prevention (DEP) violation"; 
     default: return "unknown"; 
     } 
    } 

    static const char* seDescription(const exception_code_t& code) 
    { 
     switch(code) { 
     case EXCEPTION_ACCESS_VIOLATION:   return "EXCEPTION_ACCESS_VIOLATION"   ; 
     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED" ; 
     case EXCEPTION_BREAKPOINT:    return "EXCEPTION_BREAKPOINT"    ; 
     case EXCEPTION_DATATYPE_MISALIGNMENT: return "EXCEPTION_DATATYPE_MISALIGNMENT" ; 
     case EXCEPTION_FLT_DENORMAL_OPERAND:  return "EXCEPTION_FLT_DENORMAL_OPERAND"  ; 
     case EXCEPTION_FLT_DIVIDE_BY_ZERO:  return "EXCEPTION_FLT_DIVIDE_BY_ZERO"  ; 
     case EXCEPTION_FLT_INEXACT_RESULT:  return "EXCEPTION_FLT_INEXACT_RESULT"  ; 
     case EXCEPTION_FLT_INVALID_OPERATION: return "EXCEPTION_FLT_INVALID_OPERATION" ; 
     case EXCEPTION_FLT_OVERFLOW:    return "EXCEPTION_FLT_OVERFLOW"    ; 
     case EXCEPTION_FLT_STACK_CHECK:   return "EXCEPTION_FLT_STACK_CHECK"   ; 
     case EXCEPTION_FLT_UNDERFLOW:   return "EXCEPTION_FLT_UNDERFLOW"   ; 
     case EXCEPTION_ILLEGAL_INSTRUCTION:  return "EXCEPTION_ILLEGAL_INSTRUCTION"  ; 
     case EXCEPTION_IN_PAGE_ERROR:   return "EXCEPTION_IN_PAGE_ERROR"   ; 
     case EXCEPTION_INT_DIVIDE_BY_ZERO:  return "EXCEPTION_INT_DIVIDE_BY_ZERO"  ; 
     case EXCEPTION_INT_OVERFLOW:    return "EXCEPTION_INT_OVERFLOW"    ; 
     case EXCEPTION_INVALID_DISPOSITION:  return "EXCEPTION_INVALID_DISPOSITION"  ; 
     case EXCEPTION_NONCONTINUABLE_EXCEPTION: return "EXCEPTION_NONCONTINUABLE_EXCEPTION" ; 
     case EXCEPTION_PRIV_INSTRUCTION:   return "EXCEPTION_PRIV_INSTRUCTION"   ; 
     case EXCEPTION_SINGLE_STEP:    return "EXCEPTION_SINGLE_STEP"    ; 
     case EXCEPTION_STACK_OVERFLOW:   return "EXCEPTION_STACK_OVERFLOW"   ; 
     default: return "UNKNOWN EXCEPTION" ; 
     } 
    } 

    static std::string information(struct _EXCEPTION_POINTERS* ep, bool has_exception_code = false, exception_code_t code = 0 ) 
    { 
     HMODULE hm; 
     ::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, static_cast<LPCTSTR>(ep->ExceptionRecord->ExceptionAddress), &hm); 
     MODULEINFO mi; 
     ::GetModuleInformation(::GetCurrentProcess(), hm, &mi, sizeof(mi)); 
     char fn[MAX_PATH]; 
     ::GetModuleFileNameExA(::GetCurrentProcess(), hm, fn, MAX_PATH); 

     std::ostringstream oss; 
     oss << "SE " << (has_exception_code?seDescription(code):"") << " at address 0x" << std::hex << ep->ExceptionRecord->ExceptionAddress << std::dec 
     << " inside " << fn << " loaded at base address 0x" << std::hex << mi.lpBaseOfDll << "\n"; 

     if (has_exception_code && (
      code == EXCEPTION_ACCESS_VIOLATION || 
      code == EXCEPTION_IN_PAGE_ERROR)) { 
     oss << "Invalid operation: " << opDescription(ep->ExceptionRecord->ExceptionInformation[0]) << " at address 0x" << std::hex << ep->ExceptionRecord->ExceptionInformation[1] << std::dec << "\n"; 
     } 

     if (has_exception_code && code == EXCEPTION_IN_PAGE_ERROR) { 
     oss << "Underlying NTSTATUS code that resulted in the exception " << ep->ExceptionRecord->ExceptionInformation[2] << "\n"; 
     } 

     return oss.str(); 
    } 
}; 

#include <iostream> 
#include <exception> 

void translator(InfoFromSE::exception_code_t code, struct _EXCEPTION_POINTERS* ep) 
{ 
    throw std::exception(InfoFromSE::information(ep,true,code).c_str()); 
} 

int main(int argc, char* argv[]) 
{ 
    _set_se_translator(translator); 
    try{ 
     int* p = 0; 
     std::cout << *p; 
    }catch(const std::exception& e){ 
     std::cerr << e.what() << "\n"; 
    } 

    try{ 
     int* p = 0; 
     *p = 0; 
     std::cout << *p; 
    }catch(const std::exception& e){ 
     std::cerr << e.what() << "\n"; 
    } 

    try{ 
     int a = 42; 
     volatile int b = 0; 
     std::cout << a/b; 
    }catch(const std::exception& e){ 
     std::cerr << e.what() << "\n"; 
    } 
    return 0; 
} 
相關問題