2015-02-17 15 views
7

Osoba Java tutaj utknęła robiąc C++. Wyłapuję wyjątek i próbuję zdiagnozować, skąd pochodzi (niestety wyjątek nie jest generowany podczas uruchamiania przez gdb). Jednakże, kiedy wypisuję what() wyjątku, otrzymuję po prostu ciąg "std :: exception". Czy jest to specyficzne dla czegokolwiek w standardowej bibliotece, czy też zwraca wiele standardowych wyjątków? Oto co robię do druku:std :: exception's co() zwraca "std :: wyjątek"

} catch (const std::exception & ex) { 
     std::cout << ex.what() << std::endl; 
    } 

wyjście jest tylko:

std::exception 

Również pracuję w dość dużej bazy kodu, możliwe jest, że to pochodzi z jakiś wyjątek z naszego końca, ale muszę go jeszcze znaleźć za pomocą zwykłych technik wyszukiwania, więc obecnie pochylam się nad tym, korzystając ze standardowych bibliotek.

Używam g ++ 4.8, jeśli jest to istotne.

+0

Czy otrzymujesz zrzut rdzenia, który możesz załadować do gdb i zrobić ślad śladu? –

+0

Gdzie jest zgłaszany wyjątek? Jak jest rzucany? Jaki wyjątek został zgłoszony? Utwórz [Minimalny, kompletny i weryfikowalny przykład] (http://stackoverflow.com/help/mcve) i pokaż nam. –

+0

To wydaje się niezwykłe dla wyjątku biblioteki GCC - oczekiwałbym bardziej specyficznej pochodnej klasy, takiej jak 'std :: runtime_error',' std :: length_error' itd. (Jeden z [tych] (http: //en.cppreference. com/w/cpp/error/exception)) z '.what()' komunikującym to. Myślę, że jest to prawdopodobnie z własnej bazy kodu. To może nie pomóc, ale gdybym był tobą, wypróbowałbym rekursywny grep dla '' throw \ s + std :: exception'' w twoim własnym kodzie, a jeśli to się nie pojawi, możesz wypróbować GCC nagłówki. –

Odpowiedz

3

Wyjątki C++ są całkowicie różne od wyjątków Java.

C++ standard określa, że ​​ciąg zwracany przez co() jest całkowicie arbitralne i wdrożenie zdefiniowane:

virtual const char* what() const noexcept; 

Returns: An implementation-defined ntbs. 
Remarks: The message may be a null-terminated multibyte string 
(17.5.2.1.4.2), suitable for conversion 
and display as a wstring (21.3, 22.4.1.4). The return value remains 
valid until the exception object 
from which it is obtained is destroyed or a non-const member 
function of the exception object is called. 

Wartością zwracaną dostajesz „std :: exception” jest idealnie zgodny z standard C++.

Nie polegaj na wyjątkach C++, aby dokładnie powiedzieć, skąd zostały one wyrzucone po ich przechwyceniu, tak jak robi to Java. Wykracza to poza zakres standardu C++. W C++ wyjątek jest tak naprawdę niczym więcej niż mechanizmem do przesyłania przepływu sterowania wykonaniem.

Powiedziawszy, że: wiele implementacji C++ zapewni ci pewne mechanizmy implementacji dla zrzucania bieżącego śladu po stosie, do najlepszych możliwości biblioteki środowiska wykonawczego. Sprawdź dokumentację kompilatora C++, aby uzyskać więcej informacji.

Na przykład gcc oferuje funkcję backtrace() wraz z niektórymi wewnętrznymi funkcjami gcc do konwersji nieprzetworzonych adresów zwracanych przez backtrace() na symbole i inne funkcje do odwzorowywania symboli. Używając tego, można wytworzyć szorstki analog do obsługi wyjątków Javy; chociaż implementacja gcc nie jest idealna i ma pewne luki funkcjonalne, a także wymaga wcześniejszego planowania i niestandardowych klas wyjątków, których konstruktorzy przechwytują bieżącą ramkę stosu (przed wyjątek jest faktycznie rzucany); i, po złapaniu, można rzucić wyrzuconą instancję klasy wyjątku dla przechwyconych informacji o śladach.

Ale to nie pomoże twojej obecnej sytuacji. Sugerowałbym, abyś sprawdził dokumentację kompilatora C++, tak jak zasugerowałem, a także zbadał możliwości twojego debuggera. Debuger C++ powinien umożliwiać ustawienie punktu przerwania, gdy wszystkie wyjątki są zgłaszane, a przed jego przechwyceniem, tak aby można było zbadać ślad stosu za pośrednictwem debuggera, gdy wystąpi wyjątek.

+0

Dzięki, zajrzę do śledzenia. To może uchronić mnie przed wykonaniem wyszukiwania binarnego przez całą podstawę kodu! – Pace

+0

Pomógł mi ślad wsteczny (nigdy nie udało się uzyskać prawidłowych symboli, ale udało mi się je zapisać, a następnie przesłać je do gdb, aby uzyskać lokalizacje) i udało mi się ostatecznie utorować drogę do źródła problemu. Dzięki. – Pace

+0

Ta odpowiedź sprawia, że ​​brzmi to tak, jakby komunikaty o wyjątkach były generalnie definiowane przez implementację w C++, ale dotyczy to tylko klasy bazowej 'std :: exception', a nie klas pochodnych takich jak' std :: runtime_error', gdzie 'what' jest gwarantuje zwrócenie ciągu, który przekazałeś w konstruktorze. Na przykład, §22.2.7/3 mówi: * "Postconditions:' strcmp (what(), what_arg.c_str()) == 0' * ". IOW, jeśli utworzę 'std :: runtime_error x (" foo ")', to 'what' nie może zwrócić' "std :: exception" '. –

10

To może być ze względu na dwie rzeczy:

  1. Ktoś po prostu robi throw std::exception() gdzieś, co nie jest bardzo pomocne.

  2. Klasa pochodna od zostaje skopiowana do std::exception. Jest to problem o nazwie Object Slicing.

Ja sam popełniłem drugi błąd. Miałem ten kod:

try 
{ 
    // Some Boost stuff 
} 
catch (std::exception e) 
{ 
    cerr << e.what() << endl; 
} 

Musisz się upewnić, czy robisz std::exception& e. Wiem, że nie popełniłeś tego błędu, ale możliwe, że ktoś inny zrobił dalej kod (lub ktoś przychodził tutaj z Google).

+2

Dzięki, brakowało mi &. – Tuntable

Powiązane problemy