2012-10-30 9 views
13

In caso di un'eccezione non gestita C++ voglio stampare:Posso decodificare un'eccezione C++ da un'eccezione di Windows SEH? (? E se sì, come)

  1. Il messaggio (what()) della deroga
  2. Una traccia dello stack C++.

Al fine di ottenere la traccia dello stack, sto usando SetUnhandledExceptionFilter in combinazione con il StackWalker libreria:

struct FooStackWalker : StackWalker 
{ 
    virtual void OnCallstackEntry(CallstackEntryType, CallstackEntry &entry) override 
    { 
     std::cerr << entry.lineFileName << " (" << entry.lineNumber << "): " << entry.undFullName << std::endl; 
    } 
}; 

LONG WINAPI UnhandledExceptionHandler(LPEXCEPTION_POINTERS pointers) 
{ 
    FooStackWalker walker; 
    walker.ShowCallstack(::GetCurrentThread(), pointers->ContextRecord); 
    ::TerminateProcess(::GetCurrentProcess(), 1); 
} 


int main() 
{ 
    ::SetUnhandledExceptionFilter(UnhandledExceptionHandler); 
} 

ho ottenuto l'analisi dello stack per stampare bene, ma ora ottenendo what è difficile.

Esiste un modo per decodificare l'eccezione SEH come eccezione C++ per chiamare questa funzione membro prima della conclusione?

+0

Otterrai 3 parole ExceptionInformation. Il 2 ° è un puntatore all'oggetto eccezione. Non hai alcuna speranza di interpretarlo, niente di simile a una riflessione in C++. I filtri di eccezione emessi dalla parola chiave * catch * sono cruciali. –

+0

@Hans: se si assume che la cosa generata deriva sempre da 'std :: exception' (che è vera per molte codebase), non può essere interpretata? Una volta che hai una 'std :: exception' puoi' dynamic_cast' verso i tipi di eccezione specifici se necessario ... –

+0

Invia a * what * exception? Questa è la chiave. Potresti ottenere * cosa *. –

risposta

2

Perché non utilizzare il macchinario C++ che fornisce già i dettagli delle eccezioni? Non è esclusivo con i filtri SEH (sebbene sia sia esclusivo con SetUnhandledExceptionFilter). Devi solo annidare correttamente i gestori:

int main() 
{ 
    try { 
     return cppexcept_main(); 
    } 
    catch (const std::exception& e) 
    { 
     //use e.what() 
    } 
} 

int cppexcept_main() 
{ 
    __try { 
     return application_main(); 
    } 
    __except(GrabStackTrace(GetExceptionInformation()), EXCEPTION_CONTINUE_SEARCH) { 
     /* never reached due to EXCEPTION_CONTINUE_SEARCH */ 
    } 
} 
2

Modifica: ho frainteso la tua domanda. Non posso dire con certezza quale sia la risposta alle eccezioni C++, ma sono ragionevolmente sicuro che la risposta sia "no". Non credo che ci sia un modo per distinguere tra eccezioni non gestite causate da SEH (ad esempio violazioni di accesso) e eccezioni C++ non rilevate, o qualsiasi altro modo per distinguere tra diversi tipi di eccezioni C++. Il cavallo ha già lasciato il granaio su quello.

risposta originale di seguito:


No, perché un'eccezione SEH non ha un what. Non è un std::exception. This MSDN example dice che quando stai cercando di catturare un'eccezione SEH come eccezione C++, può essere catturata solo con i puntini di sospensione (...) catch gestore. È possibile utilizzare _set_se_translator per definire la propria funzione che converte le eccezioni SEH in eccezioni C++, ma a quel punto si sta solo generando il proprio what dalle stesse informazioni in un altro posto (e anche allora, non so se sia " d essere possibile ottenerlo dallo UnhandledExceptionFilter).

Avete tutte le informazioni necessarie nello LPEXCEPTION_POINTERS structure. Se si è verificata una violazione di accesso, allora pointers->ExceptionRecord->ExceptionCode sarà EXCEPTION_ACCESS_VIOLATION (0xC0000005). Se ciò si è verificato, è possibile esaminare le variabili NumberParameters e ExceptionInformation per capire se si trattava di una violazione di lettura o scrittura e dell'indirizzo a cui si è tentato di accedere.

+0

No, voglio fare il contrario: trasformare un'eccezione SEH in un'eccezione C++.Ovviamente, se l'eccezione SEH è * not * in effetti un'eccezione C++ (MSVC++ sembra utilizzare il codice di eccezione '0xE06D7363'), qualunque conversione sia stata eseguita correttamente o non mi dirà di andare all'inferno (nel qual caso non lo faccio vuoi provare a stampare comunque una traccia dello stack - non si dovrebbe provare a continuare a correre dopo una violazione di accesso o qualsiasi altra cosa). –

+0

(Va notato che sarei felice di fare questo genere di cose all'interno di un semplice C++ 'catch', ma a quel punto lo stack è stato svolto in modo da stampare la pila del punto di lancio è impossibile) –

+0

Confermato 0xE06D7363: http : //blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx –

Problemi correlati