2010-08-19 9 views
7

Qualcuno conosce una funzione per convertire la struttura EXCEPTION_POINTERS restituita da GetExceptionInformation() in una stringa che posso registrare?Esiste una funzione per convertire la struttura EXCEPTION_POINTERS in una stringa?

Non voglio fare il mio da solo se è già stato fatto.

MODIFICA: Fondamentalmente, ho aggiunto i blocchi __try {} __except() {} per aiutare l'applicazione a fallire con garbo su un errore critico. Mentre ci sono, sto provando a registrare il più dettagliato possibile di un messaggio di errore per individuare il problema da risolvere. Idealmente, mi piacerebbe stampare il nome del file e la linea non è riuscita, ma dubito che sia possibile, quindi spero di scaricare tutte le informazioni sulle eccezioni nella speranza che saremo in grado di avvicinarci il più possibile per individuare la causa esatta del problema.

risposta

4

Non esiste una tale funzione, dal momento che avrete bisogno di simboli privati ​​per scrivere qualcosa di significativo. Il dbghelp.dll aiuta con alcuni di questi (in particolare il StackWalk function e la sua variante a 64 bit)

Cosa si vuole ottenere dal record di eccezione da inserire nel registro? Solo il codice di eccezione? Il contesto del registro? Lo stack backtrace?

EDIT: Inoltre, se si semplicemente non fare nulla, ma la registrazione per Windows Error Reporting, si può semplicemente utilizzare il servizio impressionante di Microsoft e ottenere il crash dump schiena, bucketed per popolarità. Se puoi, è di gran lunga il modo migliore per registrare i crash dump.

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

Direi che * solo * il codice e indirizzo non è particolarmente utile, in particolare con ASLR su Vista/Win7, dal momento che non è stato registrato il modulo base –

2

Non c'è molto da esso, sarete interessati nel codice eccezione e solo indirizzo. Se l'eccezione è un EXCEPTION_ACCESS_VIOLATION, allora si desidera anche scaricare i primi due valori di ExceptionInformation. Il primo indica l'operazione (0 = lettura, 1 = scrittura, 8 = prevenzione esecuzione dati), la seconda fornisce l'indirizzo di errore.

+1

Oltre a 0 e 1, c'è anche 8, "Se questo valore è 8, il thread causa una violazione di esecuzione dei dati (DEP) in modalità utente." da "struttura EXCEPTION_RECORD" http://msdn.microsoft.com/en-us/library/windows/desktop/aa363082(v=vs.85).aspx –

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; 
} 
Problemi correlati