2012-10-30 7 views
13

W razie nieobsługiwany wyjątek C++ chcę wydrukować:Czy mogę odszyfrować wyjątek C++ z wyjątku Windows SEH? (? A jeśli tak, to w jaki sposób)

  1. Komunikat (what()) z C++ wyjątkiem
  2. ślad stosu.

aby uzyskać ślad stosu, używam SetUnhandledExceptionFilter w połączeniu z StackWalker Biblioteka:

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

stałam ślad stosu do wydrukowania po prostu w porządku, ale teraz jest coraz what trudny.

Czy jest jakiś sposób mogę odszyfrować wyjątek SEH jako wyjątek C++, aby wywołać tę funkcję członka przed zakończeniem?

+0

Otrzymasz 3 słowa ExceptionInformation. Druga to wskaźnik do obiektu wyjątku. Nie masz nadziei na jej interpretację, nie ma czegoś takiego jak odbicie w C++. Filtry wyjątków emitowane przez słowo kluczowe * catch * są kluczowe. –

+0

@Hans: Jeśli założymy, że rzecz wyrzucona zawsze pochodzi od 'std :: exception' (co jest prawdą w wielu bazach kodów), to czy nie można tego zinterpretować? Gdy masz 'std :: exception' możesz' dynamic_cast' w dół do określonych typów wyjątków, jeśli trzeba ... –

+0

Prześlij na * co * wyjątek? To jest klucz. Możesz dostać * co *. –

Odpowiedz

2

Dlaczego nie użyć maszyny C++, która już podaje szczegóły wyjątku? Nie jest to wyłączne z filtrami SEH (chociaż jest to jest wyłączne z wyłącznie z SetUnhandledExceptionFilter). Trzeba po prostu poprawnie zagnieździć handlerów:

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

Edytuj: Źle zrozumiałem twoje pytanie. Nie mogę powiedzieć na pewno, jaka jest odpowiedź na wyjątki C++, ale jestem dość pewna, że ​​odpowiedź brzmi "nie". Nie sądzę, że istnieje sposób na rozróżnienie między nieobsługiwanymi wyjątkami spowodowanymi przez SEH (np. Naruszenia zasad dostępu) i wyjątkami C++ bez przechwytywania lub sposobem na rozróżnienie różnych typów wyjątków C++. Koń opuścił już stodołę.

odpowiedź Original poniżej:


Nie, ponieważ wyjątek SEH nie posiada what. To nie jest std::exception. This MSDN example mówi, że gdy próbujesz uchwycić wyjątek SEH jako wyjątek C++, można go złapać tylko za pomocą obsługi wielokropka (...) catch. Możesz użyć _set_se_translator do zdefiniowania swojej własnej funkcji, która konwertuje wyjątki SEH do wyjątków C++, ale w tym momencie po prostu generujesz swój własny what z tej samej informacji w innym miejscu (a nawet wtedy, nie wiem, czy to ". d będzie można uzyskać z niego od UnhandledExceptionFilter).

Masz wszystkie informacje potrzebne w LPEXCEPTION_POINTERS structure. Jeśli doszło do naruszenia zasad dostępu, wówczas pointers->ExceptionRecord->ExceptionCode będzie(0xC0000005). Jeśli tak się stało, możesz sprawdzić zmienne NumberParameters i ExceptionInformation, aby dowiedzieć się, czy było to naruszenie odczytu lub zapisu oraz adres, który próbował uzyskać dostęp.

+0

Nie, chcę zrobić odwrotnie - włącz wyjątek SEH do wyjątku C++.Oczywiście, jeśli wyjątek SEH jest * nie * w rzeczywistości wyjątek C++ (MSVC++ wydaje się używać kod wyjątku "0xE06D7363"), niezależnie od konwersji zrobić darmo, aby zawieść lub w inny sposób powiedzieć mi iść do piekła (w takim przypadku nie mam chcesz spróbować wydrukować ślad stosu - nie należy próbować kontynuować działania po naruszeniu dostępu lub cokolwiek innego). –

+0

(Należy zauważyć, że byłbym szczęśliwy, robiąc tego rodzaju rzeczy wewnątrz zwykłego "catch" C++, ale w tym momencie stos został rozwinięty, więc drukowanie stosu punktu rzutu jest niemożliwe) –

+0

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

Powiązane problemy