Führen Sie eine Anwendung in GDB aus, bis eine Ausnahme auftritt

102

Ich arbeite an einer Multithread-Anwendung und möchte sie mit GDB debuggen.

Das Problem ist, einer meiner Threads stirbt immer wieder mit der Nachricht:

pure virtual method called
terminate called without an active exception
Abort

Ich kenne die Ursache dieser Nachricht, habe aber keine Ahnung, wo sie in meinem Thread auftritt. Eine Rückverfolgung wäre wirklich hilfreich.

Wenn ich meine App in GDB ausführe, wird sie jedes Mal angehalten, wenn ein Thread angehalten oder fortgesetzt wird. Ich möchte, dass meine App normal weiterläuft, bis einer der Threads mit dieser Ausnahme stirbt. An diesem Punkt sollte alles angehalten werden, damit ich eine Rückverfolgung erhalten kann.

Ankur Sethi
quelle
Welches Signal meldet die GDB, wenn sie pausiert? Sie sollten in der Lage sein, einen Befehl wiehandle SIGUSR1 pass noprint nostop
Hasturkun

Antworten:

147

Sie können versuchen, catch throwden Debugger mit einem "catchpoint" ( ) an dem Punkt zu stoppen, an dem die Ausnahme generiert wird.

Der folgende Auszug aus dem GDB-Handbuch beschreibt die Catchpoint-Funktion.


5.1.3 Fangpunkte setzen

Sie können Catchpoints verwenden, um den Debugger für bestimmte Arten von Programmereignissen anzuhalten, z. B. für C ++ - Ausnahmen oder das Laden einer gemeinsam genutzten Bibliothek. Verwenden Sie den Befehl catch, um einen catchpoint festzulegen.

  • Ereignis fangen

    Stoppen Sie, wenn ein Ereignis eintritt. Ereignis kann eines der folgenden sein:

    • werfen

      Das Auslösen einer C ++ - Ausnahme.

    • Fang

      Das Abfangen einer C ++ - Ausnahme.

    • exec

      Ein Anruf an exec. Dies ist derzeit nur für HP-UX verfügbar.

    • Gabel

      Ein Ruf zur Gabelung. Dies ist derzeit nur für HP-UX verfügbar.

    • vfork

      Ein Anruf bei vfork. Dies ist derzeit nur für HP-UX verfügbar.

    • Laden oder Laden von libname

      Das dynamische Laden einer gemeinsam genutzten Bibliothek oder das Laden des Bibliotheksbibliotheksnamens. Dies ist derzeit nur für HP-UX verfügbar.

    • libname entladen oder entladen

      Das Entladen einer dynamisch geladenen gemeinsam genutzten Bibliothek oder das Entladen der Bibliothek libname. Dies ist derzeit nur für HP-UX verfügbar.

  • tcatch Ereignis

    Legen Sie einen Fangpunkt fest, der nur für einen Stopp aktiviert ist. Der Catchpoint wird automatisch gelöscht, nachdem das Ereignis zum ersten Mal abgefangen wurde.

Verwenden Sie den info breakBefehl, um die aktuellen Fangpunkte aufzulisten.

Derzeit gibt es einige Einschränkungen bei der Behandlung von C ++ - Ausnahmen (Catch Throw und Catch Catch) in GDB:

  • Wenn Sie eine Funktion interaktiv aufrufen, gibt GDB normalerweise die Kontrolle an Sie zurück, wenn die Ausführung der Funktion abgeschlossen ist. Wenn der Aufruf jedoch eine Ausnahme auslöst, kann der Aufruf den Mechanismus umgehen, der Ihnen die Kontrolle zurückgibt, und dazu führen, dass Ihr Programm entweder abgebrochen wird oder einfach weiter ausgeführt wird, bis es einen Haltepunkt erreicht, ein Signal abfängt, auf das GDB wartet, oder beendet wird. Dies ist auch dann der Fall, wenn Sie einen Catchpoint für die Ausnahme festlegen. Fangpunkte für Ausnahmen sind in interaktiven Anrufen deaktiviert.

  • Sie können eine Ausnahme nicht interaktiv auslösen.

  • Sie können einen Ausnahmebehandler nicht interaktiv installieren.

Manchmal ist catch nicht der beste Weg, um die Ausnahmebehandlung zu debuggen: Wenn Sie genau wissen müssen, wo eine Ausnahme ausgelöst wird, sollten Sie anhalten, bevor der Ausnahmebehandler aufgerufen wird, da Sie auf diese Weise den Stapel sehen können, bevor ein Abwickeln stattfindet. Wenn Sie stattdessen einen Haltepunkt in einem Ausnahmehandler festlegen, ist es möglicherweise nicht einfach herauszufinden, wo die Ausnahme ausgelöst wurde.

Um zu stoppen, bevor ein Ausnahmebehandler aufgerufen wird, benötigen Sie einige Kenntnisse über die Implementierung. Im Fall von GNU C ++ werden Ausnahmen durch Aufrufen einer Bibliotheksfunktion mit dem Namen __raise_exception ausgelöst, die über die folgende ANSI C-Schnittstelle verfügt:

/* addr is where the exception identifier is stored.
   id is the exception identifier.  */
void __raise_exception (void **addr, void *id);

Setzen Sie einen Haltepunkt auf __raise_exception, damit der Debugger alle Ausnahmen abfängt, bevor ein Stapel abgewickelt wird (siehe Abschnitt Haltepunkte, Überwachungspunkte und Ausnahmen).

Mit einem bedingten Haltepunkt (siehe Abschnitt Unterbrechungsbedingungen), der vom Wert von id abhängt, können Sie Ihr Programm stoppen, wenn eine bestimmte Ausnahme ausgelöst wird. Sie können mehrere bedingte Haltepunkte verwenden, um Ihr Programm zu stoppen, wenn eine Reihe von Ausnahmen ausgelöst wird.

Dan
quelle
Sie können auch die Art der Ausnahme angeben, die abgefangen werden soll, z catch throw std::runtime_exception.
Scai
5

Setzen Sie einen Haltepunkt auf __pure_virtual

Steve Folly
quelle
In der Antwort von @JeffreyHill heißt es jetzt __cxa_pure_virtual. Ich weiß nicht, wie ich das selbst überprüfen soll, daher möchte ich die Antwort nicht bearbeiten. Ich habe nicht vor, abzustimmen, aber die Antwort könnte jetzt falsch sein und sollte von jemandem bearbeitet werden, der weiß, was richtig ist.
Philipp Claßen
5

FWIW hat sich anscheinend in gcc 4.1 der entsprechende Funktionsname geändert und man muss in dieser Funktion einen Haltepunkt setzen.

__cxa_pure_virtual

Jeffrey Hill
quelle
0

Nur unten hat einer mit gdb 8.3 für mich gearbeitet:

break _Unwind_RaiseException

"catch throw" oder "break __cxx_throw" hat bei mir nicht funktioniert.

soumeng78
quelle