2012-09-05 8 views
7

Czy istnieje sposób, aby spowodować rzut w C++, aby zrzucić rdzeń w miejscu rzutu, jeśli wyrzucony wyjątek byłby obsługiwany przez pewien połów blok? Chciałbym czegoś podobnego do tego, co dzieje się z g ++, gdy wyjątek osiągnie najwyższy poziom.Jak spowodować zrzut C++ do zrzutu jądra, jeśli wyjątek byłby obsługiwany przez konkretny blok catch

Na przykład, chciałbym coś takiego:

try { 
    bar(); 
    try { 
    foo(); 
    } catch(...) { 
# pragma dump_at_throw_site 
    } 
} catch(...) { 
    std::cerr << "There was a problem" << std::endl; 
} 

ten sposób, jeśli każdy wyjątek wyrzucony z foo() lub jego wywoływany, że dochodzi do połączenia zakładowych Foo() spowodowałoby zrzutu na stronie rzutu, więc można zobaczyć, kto rzucił wyjątek, który dotarł do tego poziomu.

Z drugiej strony wyjątki generowane przez bar() będą obsługiwane normalnie.

+1

Myślę, że zwykłą metodą jest po prostu nie łapanie go i mam nadzieję, że kompilator/środowisko zrobi dla ciebie zrzut. Informacja o stronie rzutu traci wartość _instant_ po wyrażeniu 'throw'. –

+0

Właśnie dlatego chcę, aby kompilator wygenerował logikę dla zrzutu pamięci, aby stos nie został rozwinięty. Jest to możliwe, ponieważ dzieje się tak dokładnie, gdy blokada * no * catch kończy się aż do katalogu głównego łańcucha wywołań. Istnieją jednak zewnętrzne bloki przechwytujące, które wychwycą wyjątek w moim przypadku. Bardzo chciałbym zrzucić rdzeń na stronie throw dla foo() jak w przykładzie i zignorować wyjątki z paska. Mogę żyć z odpowiedzią określoną przez ++ lub g ++. – Manish

+1

W takim przypadku strona _throw_ musi wygenerować zrzut rdzenia, a nie catchee. Jednak jedną z opcji jest wygenerowanie zrzutu pamięci w pewnej wewnętrznej strukturze, zapisanie tej informacji w wyjątku, a _ then_ wyrzucenie wyjątku. _Then_ catchee może zrobić coś z tą informacją o zrzucie. –

Odpowiedz

2

Tak, może w systemie Windows. Nie znam Linuksa, przypuśćmy, że to też może.

Możemy przypisać funkcję Exception Handler od odpowiedzi throw przed catch Oto przykładowy kod:

#include <iostream> 
#include "windows.h" 
#define CALL_FIRST 1 
LONG WINAPI 
VectoredHandler(
    struct _EXCEPTION_POINTERS *ExceptionInfo 
    ) 
{ 
    UNREFERENCED_PARAMETER(ExceptionInfo); 
    std::cout <<"VectoredHandler"<<std::endl; 
    return EXCEPTION_CONTINUE_SEARCH; 
} 
int main() 
{ 
    PVOID handler; 
    handler = AddVectoredExceptionHandler(CALL_FIRST,VectoredHandler); 

    try { 
     throw 1; 
    }catch(...) 
    { 
     std::cout <<"catch (...)"<< std::endl; 
    } 

    RemoveVectoredExceptionHandler(handler); 
    std::cout << "end of main"<<std::endl; 
    return 0; 
} 

Wyjścia kodu są:

VectoredHandler 
catch (...) 
end of main 

Tak, można zrzucić rdzeń int funkcji VectoredHandler. Funkcja VectoredHandler jest wywoływana po tym, jak debugger otrzyma powiadomienie o pierwszej szansie, ale zanim system rozpocznie rozwijanie stosu. A jeśli Twoim celem jest tylko debugowanie problemu, możesz polegać na funkcji debuggera, aby obsłużyć wyjątek pierwszej szansy, nie trzeba zrzucać aplikacji.

Dla twojej informacji, możesz potrzebować znać What is a First Chance Exception? w Windows, aby zrozumieć, w jaki sposób Windows wysyła wyjątek.

Powiązane problemy