2013-05-01 5 views

Antwort

8

Aktualisiert


Hier einige Informationen aus der GDB-Handbuch

Es liegen noch einige Einschränkungen C++ Ausnahmebehandlung (Fang Wurf und Beifang) in GDB:

Wenn Sie eine Funktion interaktiv aufrufen, gibt gdb normalerweise die Kontrolle an Sie zurück, wenn die Funktion hat fertig ausgeführt. Wenn der Aufruf eine Ausnahme auslöst, kann der Aufruf jedoch den Mechanismus umgehen, der Steuerung an Sie zurückgibt und Ihr Programm entweder abbrechen oder fortsetzen, bis es einen Haltepunkt erreicht, ein Signal abfängt, das gdb wartet oder beendet. Dies ist auch dann der Fall, wenn Sie für die Ausnahme einen Catchpoint setzen; Zwischenrufe bei Ausnahmen sind in interaktiven Anrufen deaktiviert. Sie können eine Ausnahme nicht interaktiv auslösen. Sie können einen Ausnahmehandler nicht interaktiv installieren. Manchmal catch ist nicht der beste Weg, um die Ausnahmebehandlung zu debuggen: wenn Sie wissen müssen genau, wo eine Ausnahme ausgelöst wird, ist es besser zu stoppen, bevor die Ausnahmeroutine aufgerufen wird, da auf diese Weise Sie den Stapel vor jedem sehen können die Abwicklung findet statt. Wenn Sie stattdessen einen Haltepunkt in einem Exception-Handler festlegen, ist es möglicherweise nicht einfach herauszufinden, wo die Ausnahme ausgelöst wurde.

Um kurz vor dem Aufruf eines Exception-Handlers zu stoppen, benötigen Sie einige Kenntnisse der Implementierung. Im Fall von Gnu C++, Ausnahmen durch den Aufruf einer Bibliotheksfunktion namens __raise_exception angehoben werden, die die folgenden ANSI-C-Schnittstelle:

 /* addr is where the exception identifier is stored. 
     id is the exception identifier. */ 
    void __raise_exception (void **addr, void *id); To make the debugger catch all exceptions before any stack unwinding takes place, 

einen Haltepunkt auf __raise_exception (siehe Haltepunkte, Beobachtungspunkte; und Ausnahmen).


Das heißt

Es hängt von der Code und wo Sie in dem Stapel sind. Wenn Sie tatsächlich die Ausnahme wie in gefangen:

try { .... } catch (std::exception &e) { 
    //do stuff 
} 

könnten Sie versuchen, wahrscheinlich e.what() Druck oder bei den Mitgliedern der Ausnahme betrachten. Wenn Sie es gerade als (...) gefangen haben, dann bin ich mir nicht sicher, was Sie sammeln könnten.

Eine andere Sache, die Sie tun können, ist 'werfen' in gdb und fangen 'fangen' auch, wenn Sie wirklich den ganzen Fluss folgen wollen.

gdb> catch catch 
gdb> catch throw 

Auf diese Weise werden Sie einen Haltepunkt richtig machen, bevor Ausnahmen geworfen werden und richtig, da sie gefangen sind, können Sie dann den Stapel gehen mehr Informationen darüber zu gewinnen, was los war. Selbst wenn Sie sich in einem anderen Haltepunkt befinden, sollten Sie in der Lage sein, den Stapel zu durchlaufen (mit den Pfeiltasten nach oben oder nach unten), um den Rahmen zu erhalten, in dem die Ausnahme sichtbar ist.

3

Kurze Antwort: Sie können nicht, weil die meiste Arbeit der Ausnahmebehandlung außerhalb Ihres Programms getan wird, und deshalb außerhalb des Umfangs von gdb ist.

Erklärung der Antwort:

manchmal die Linie eine Ausnahme ausgelöst hat keine Symbole

Wenn die binäre Sie Debuggen keine Debug-Symbole hat dann die binäre wahrscheinlich abgestreift wird und Sie gewonnen‘ Ich kann überhaupt nicht viel über die Arten/Werte von irgendetwas herausfinden.

Wie überprüfe ich den Wert der aktuellen Ausnahme?

Ich denke, Sie gehen hier davon aus, dass eine Ausnahme eine Sprachfunktion ist, die gdb inspizieren kann; Eine Ausnahme in C++ ist eine Kombination von Features aus C++ als Sprache, aus libC++ und dem ABI. Und es könnte sogar mehr als eine einzige aktive Ausnahme geben. Wie UpAndAdam darauf hinweist, können Sie einen Haltepunkt in einem Fangblock mit einem Typspezifizierer festlegen und dann dieses Element untersuchen, aber ich vermute, dass Ihr Problem in Fällen liegt, in denen Sie ein "catch (...)" finden. In diesen Fällen können Sie nicht viel über die aktuelle Ausnahme erfahren, es sei denn, Sie befassen sich mit der Implementierung der Ausnahmebehandlung.

Bei einer sehr kurzen und unvollständigen Beschreibung wir, dass eine Ausnahme werfen könnten sagen:

  1. Ihr Programm ruft ++ libc eine Ausnahme
  2. zu erhöhen libC++ rufen „entspannen“ in glibc den Stapel zu starten Abwickeln
  3. Abwickelstation wird eine „Persönlichkeit Funktion“ von libC++ für jeden Stapelrahmen (jeder Funktionsaufruf in dem Stapel, im Allgemeinen)
  4. die Persönlichkeit funktionieren kann, wenn der aktuelle Stapelrahmen irgendwie entscheiden Rückruf oder diese nicht verarbeiten kann Ausnahme
  5. , wenn die Ausnahme kann der Block catch behandelt werden

nun ausgeführt werden, ist es schwierig, über Details zu sprechen, weil viele Ausnahmebehandlung auf Ihrem Werkzeugkette hängt (Compiler, Plattform, Architektur, libC++, etc.) aber in den meisten Fällen wird ein "catch (...)" nicht einmal die ursprüngliche Ausnahme als Argument erhalten. Auf jeden Fall beantworten irgendwie Ihre Frage: in gcc mit GNUs libC++ Sie so etwas wie dies versuchen könnte:

  1. Holen Sie sich ein libC++ mit Bugsymbol
  2. einen Haltepunkt in __gxx_personality_v0 Set (das die Persönlichkeit Funktion genannt).Diese Funktion wird aufgerufen, um zu bestimmen, ob ein Stapelrahmen (im Prinzip ein Funktionsaufruf) über einen geeigneten catch-Block verfügt, um die Ausnahme zu behandeln
  3. In der Personality-Funktion können Sie einen Zeiger auf _Unwind_Exception finden, der ein Wrapper ist zu Ihrer echten Ausnahme
  4. Erhalten Sie die Typinfo für Ihre Ausnahme wie folgt: __cxa_exception * exception_header = (__cxa_exception *) (abwicklung_exception + 1) -1; std :: type_info * geworfene_exception_type = exception_header-> exceptionType;
  5. Sie erhalten eine Ausnahme-Typ erhalten, die Sie dann mit dem Rest des RTTI definiert für Ihren Code

In jedem Fall Nachschlag kann, müssen Sie wahrscheinlich versuchen, ziemlich viel Zeit damit verbringen, zu verstehen, wie die Ausnahmebehandlung in Ihrer Plattform implementiert ist. Wenn Sie etwas mehr über die Ausnahmebehandlung lesen möchten, habe ich in der Vergangenheit etwas über das Thema @http://monoinfinito.wordpress.com/series/exception-handling-in-c/ geschrieben. Es ist keine offizielle Quelle, aber es enthält Links zu den Spezifikationen jedes Teils, der an der Behandlung einer Ausnahme beteiligt ist.

3

Diese Antworten waren korrekt, wenn sie geschrieben wurden, aber seither haben sich gdb und libstdC++ geändert.

libstdC++ hat jetzt einige Hooks, die gdb besser mit dem Ausnahmesystem interagieren lassen. Insbesondere gibt es nun genügend Informationen für gdb, um dem Benutzer eine $_exception Convenience-Variable bereitzustellen. Diese Variable enthält die Ausnahme, die ausgelöst wird. Es ist nur an genau der Stelle gültig, an der die Ausnahme abgefangen wird; mit dem Sie aufhören können, catch catch zu verwenden.

Weitere Informationen finden Sie unter the page from the manual.

Verwandte Themen