Debugging mit gdb

Mit dem GNU Debugger (gdb) können Sie die internen Abläufe eines anderen Programms prüfen, während das Programm ausgeführt wird, oder nachträglich sehen, welche Operationen ein Programm zu dem Zeitpunkt ausgeführt hat, als es abgestürzt ist.

Mit dem Befehl gdb können Sie die Ausführung von Code prüfen und steuern. Er ist auch bei der Auswertung der Ursachen von Abstürzen oder von allgemeinem falschem Verhalten hilfreich. gdb verarbeitet keine Java™ -Prozesse, daher ist die Verwendung in einem reinen Java-Programm eingeschränkt. Sie ist nützlich für das Debugging von nativen Bibliotheken und der JVM selbst.

gdb ausführen

Sie können gdb auf drei Arten ausführen:

Programm starten
Normalerweise wird der Befehl gdb <application> verwendet, um ein Programm unter der Steuerung von gdbzu starten. Aufgrund der Art und Weise, wie Java gestartet wird, müssen Sie gdb jedoch starten, indem Sie eine Umgebungsvariable festlegen und anschließend Java aufrufen:
export IBM_JVM_DEBUG_PROG=gdb
java
Anschließend erhalten Sie eine gdb -Eingabeaufforderung und geben den Ausführungsbefehl und die Java-Argumente an:
r <java_arguments>
An ein aktives Programm anhängen
Wenn ein Java-Programm bereits ausgeführt wird, können Sie es unter gdbsteuern. Die Prozess-ID des aktiven Programms ist erforderlich und anschließend wird gdb mit der Java-Anwendung als erstem Argument und der Prozess-ID als zweitem Argument gestartet:
gdb <Java Executable> <PID>

Wenn gdb an ein aktives Programm angehängt wird, wird dieses Programm angehalten und seine Position im Code wird für die Anzeigefunktion angezeigt. Das Programm unterliegt dann der Steuerung von gdb und Sie können damit beginnen, Befehle auszugeben, um die Variablen festzulegen und anzuzeigen und die Ausführung des Codes im Allgemeinen zu steuern.

Für einen Systemspeicherauszug (Kerndatei) ausführen
Wenn ein Programm abstürzt, wird normalerweise ein Systemspeicherauszug erstellt. gdb kann für diesen Systemspeicherauszug ausgeführt werden. Der Systemspeicherauszug enthält den Status des Programms zu dem Zeitpunkt, als der Absturz aufgetreten ist. Prüfen Sie mit gdb die Werte aller Variablen und Register, die zu einem Absturz geführt haben. Mithilfe dieser Informationen können Sie die Ursache des Absturzes ermitteln. Zum Debuggen eines Systemspeicherauszugs starten Sie gdb mit der Java-Anwendungsdatei als erstem Argument und dem Namen des Systemspeicherauszugs als zweitem Argument:
gdb <Java Executable> <system dump>

Wenn Sie gdb für einen Systemspeicherauszug ausführen, werden zunächst Informationen wie das Beendigungssignal, das das Programm empfangen hat, die Funktion, die zu dem Zeitpunkt ausgeführt wurde, und sogar die Codezeile, die den Fehler generiert hat, angezeigt.

Wenn ein Programm von gdbgesteuert wird, wird eine Willkommensnachricht gefolgt von einer Eingabeaufforderung (gdb) angezeigt. Das Programm wartet jetzt darauf, dass Sie Anweisungen eingeben. Bei jeder Anweisung fährt das Programm so fort, wie Sie es wünschen.

Haltepunkte und Überwachungspunkte festlegen

Haltepunkte können mit dem folgenden Befehl für eine bestimmte Zeile oder Funktion festgelegt werden:

break linenumber

oder

break functionName

Nachdem Sie einen Haltepunkt festgelegt haben, verwenden Sie den Befehl continue, um die Ausführung eines Programms bis zu einem Haltepunkt zuzulassen.

Legen Sie Haltepunkte mit Bedingungen fest, sodass das Programm nur angehalten wird, wenn die angegebene Bedingung erfüllt ist. Wenn Sie beispielsweise breakpoint 39 if var == value verwenden, wird das Programm angehalten, wenn es Zeile 39 erreicht, aber nur, wenn die Variable dem angegebenen Wert entspricht.

Wenn Sie wissen möchten, wo und wann eine Variable einen bestimmten Wert angenommen hat, können Sie einen Überwachungspunkt verwenden. Legen Sie den Überwachungspunkt fest, wenn die fragliche Variable gültig ist. Danach werden Sie immer benachrichtigt, wenn diese Variable den angegeben Wert annimmt. Die Syntax des Befehls lautet: watch var == value.

Um festzustellen, welche Haltepunkte und Überwachungspunkte festgelegt sind, verwenden Sie den Befehl info:

info break
info watch
Wenn gdb einen Haltepunkt oder Überwachungspunkt erreicht, wird die Codezeile ausgegeben, die als Nächstes ausgeführt werden soll. Das Setzen eines Unterbrechungspunkts in Zeile 8 führt dazu, dass das Programm nach Abschluss der Ausführung von Zeile 7, aber vor Ausführung von Zeile 8 angehalten wird. Neben Unterbrechungspunkten und Überwachungspunkten stoppt das Programm auch, wenn es bestimmte Systemsignale empfängt. Mithilfe der folgenden Befehle können Sie verhindern, dass das Debugging-Tool jedes Mal anhält, wenn es diese Systemsignale erhält:
handle sig32 pass nostop noprint 
handle sigusr2 pass nostop noprint 

Code prüfen

Wenn die richtige Codeposition erreicht wurde, gibt es eine Reihe von Methoden, mit denen der Code geprüft werden kann. Die hilfreichste Methode ist die Verwendung von backtrace (abgekürzt: bt), womit der Aufrufstack angezeigt wird. Beim Aufrufstack handelt es sich um die Sammlung von Funktionsframes, wobei jeder Funktionsframe Informationen wie Funktionsparameter und lokale Variablen enthält. Diese Funktionsframes werden im Aufrufstack in der Reihenfolge platziert, in der sie ausgeführt werden. Das heißt, dass die zuletzt aufgerufene Funktion im Aufrufstack ganz oben angezeigt wird. Sie können den Ausführungspfad eines Programms verfolgen, indem Sie den Aufrufstack prüfen. Wenn der Aufrufstack angezeigt wird, wird am Zeilenanfang eine Framenummer angezeigt, danach die Adresse der aufrufenden Funktion sowie der Funktionsname und die Quellendatei für die Funktion. Beispiel:
#6 0x804c4d8 in myFunction () at myApplication.c

Verwenden Sie zum Anzeigen detaillierterer Informationen zu einem Funktionsframe den Befehl frame zusammen mit einem Parameter, der die Framenummer angibt. Nachdem Sie einen Rahmen ausgewählt haben, können Sie dessen Variablen mit dem Befehl print varanzeigen.

Verwenden Sie den Befehl print, um den Wert einer Variablen zu ändern. Beispiel: print var = newValue.

Mit dem Befehl info locals werden die Werte aller lokalen Variablen in der ausgewählten Funktion angezeigt.

Um die genaue Ausführungsreihenfolge Ihres Programms zu verfolgen, verwenden Sie die Befehle step und next. Beide Befehle können einen optionalen Parameter enthalten, der die Anzahl der Zeilen angibt, die ausgeführt werden sollen. next behandelt Funktionsaufrufe jedoch als eine einzige Ausführungszeile, während step die einzelnen Zeilen der aufgerufenen Funktion schrittweise durchgeht.

Nützliche Befehle

Wenn Sie das Debugging Ihres Codes beendet haben, bewirkt der Befehl run, dass das Programm bis zum Ende oder bis zum Absturzpunkt ausgeführt wird. Mit dem Befehl quit können Sie gdb beenden.

Die folgenden Befehle können hilfreich sein:

ptype
Gibt den Datentyp der Variablen aus.
info share
Gibt die Namen der gemeinsam genutzten Bibliotheken aus, die derzeit geladen sind.
info functions
Gibt alle Funktionsprototypen aus.
list
Zeigt die 10 Zeilen Quellcode um die aktuelle Zeile herum an.
help
Zeigt eine Liste mit Themen an, für die der Hilfebefehl aufgerufen werden kann, um eine detaillierte Hilfe zu dem entsprechenden Thema anzuzeigen.