Lässt es sich mit cremefarbenem Papier, einer Tönung, mehr Kontrast oder größerer Schrift besser lesen? Wählen Sie Ihre Farben und Ihre Schrift, einmalig für alle Seiten.

Kostenlose Lektion

Fehlersuche mit dem Debugger gdb

Nach dieser Lektion: Ich kann mit einem Debugger die Zeile finden, in der ein Programm abstürzt.

Lektion, 65 Min.7 BefehleLab für Compilerbau und Rechnerarchitektur: gcc, flex, bison und RISC-V in einer VM

Wie findet man die Zeile eines Absturzes?

Ein Debugger ist ein Werkzeug, das ein Programm anhält und zeigt, in welcher Zeile es steht und welche Werte seine Variablen haben. Mit gdb finden Sie die Zeile eines Absturzes, ohne überall printf einzufügen.

Eine Notenverwaltung rechnet zum Beispiel einen falschen Durchschnitt aus. Mit einem Haltepunkt sehen Sie die Werte genau dort, wo der Fehler entsteht.

Am Ende dieser Lektion

Notiz

Ich kann mit einem Debugger die Zeile finden, in der ein Programm abstürzt.

Schlüsselwörter

BegriffWas er bedeutetBeispiel
Debuggerein Werkzeug, das ein Programm schrittweise untersuchtgdb
Haltepunkteine Stelle, an der das Programm anhältbreak main
Backtracedie Liste der gerade aktiven Funktionsaufrufebt
Signaleine Meldung des Systems an einen ProzessSIGSEGV
Absturzein unfreiwilliges Ende durch ein Signal
DebuginformationenZeilen und Namen, die gcc mit der Option -g ablegt

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Ein Haltepunkt zeigt die Werte mitten im Lauf

Übersetzen Sie mit gcc -g, dann legt gcc Debuginformationen ab: Zeilennummern und Namen. Ohne sie kennt gdb nur Adressen.

Mit break durchschnitt setzen Sie einen Haltepunkt. gdb hält dort an, print zeigt Variablen, und next führt eine Zeile aus. Das Programm unten teilt 17 Punkte auf 4 Personen und gibt 4 aus statt 4,25.

Das Programm debug.c

Code: c
#include <stdio.h>
int durchschnitt(int summe, int anzahl) {
    int ergebnis = summe / anzahl;
    return ergebnis;
}
int main(void) {
    int punkte = 17;
    int personen = 4;
    printf("Durchschnitt %d\n", durchschnitt(punkte, personen));
    return 0;
}

In den Arbeitsordner wechseln

Befehl
mkdir -p ~/csys && cd ~/csys

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Das Programm in eine Datei schreiben

Befehl
printf '#include <stdio.h>\nint durchschnitt(int summe, int anzahl) {\n    int ergebnis = summe / anzahl;\n    return ergebnis;\n}\nint main(void) {\n    int punkte = 17;\n    int personen = 4;\n    printf("Durchschnitt %%d\\n", durchschnitt(punkte, personen));\n    return 0;\n}\n' > debug.c

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Mit Debuginformationen übersetzen

Befehl
gcc -g -O0 -o debug debug.c

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Anhalten, Werte lesen, eine Zeile weitergehen

Befehl
gdb -batch -ex 'break durchschnitt' -ex run -ex 'print summe' -ex 'print anzahl' -ex next -ex 'print ergebnis' -ex bt ./debug 2>&1 | grep -E '^(#0|\$|Breakpoint 1,)'

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Beispiel: was die fünf Zeilen bedeuten

Zeile der AusgabeBedeutung
Breakpoint 1, durchschnitt (summe=17, anzahl=4) at debug.c:3Halt vor Zeile 3, mit den Parametern
$1 = 17Der erste print: summe
$2 = 4Der zweite print: anzahl
$3 = 4ergebnis nach next: 17 geteilt durch 4 ergibt ganzzahlig 4
#0 durchschnitt (summe=17, anzahl=4) at debug.c:4Der Backtrace: jetzt steht das Programm in Zeile 4

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Ein Absturz ist ein Signal an den Prozess

Passiert etwas Unmögliches, schickt das System dem Prozess ein Signal und beendet ihn. Das ist ein Absturz. gdb fängt das Signal ab und zeigt, wo es ankam.

Das Programm unten bricht mit assert selbst ab, weil personen 0 ist. Das ist wohldefiniert und ein sicheres Beispiel. Den Zugriff auf NULL oder die Division durch null führen wir nie aus, denn ihr Ergebnis ist in C undefiniert.

Ein Programm mit einer Prüfung schreiben

Befehl
printf '#include <stdio.h>\n#include <stdlib.h>\n#include <assert.h>\nint main(void) {\n    int personen = 0;\n    assert(personen > 0);\n    return 0;\n}\n' > absturz.c

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Mit Debuginformationen übersetzen

Befehl
gcc -g -O0 -o absturz absturz.c

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Den Absturz in gdb lesen

Befehl
gdb -batch -ex run ./absturz 2>&1 | grep -E 'Assertion|SIGABRT'

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Beispiel: häufige Signale eines Absturzes

SignalNummerBedeutung
SIGSEGV11ungültiger Zugriff auf den Speicher
SIGFPE8ein Rechenfehler, etwa Teilen durch null
SIGABRT6das Programm bricht sich selbst ab, etwa mit assert
SIGBUS7ein Zugriff, den die Hardware nicht erlaubt

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

So lesen Sie einen Absturzbericht

Ein Bericht hat zwei Teile. Die Zeile Program received signal nennt das Signal und damit die Art des Fehlers. Die Zeile #0 des Backtrace nennt Funktion, Datei und Zeile, in der es geschah.

Die Zeile #1 nennt den Aufrufer. So gehen Sie rückwärts, bis Sie den Wert finden, der falsch war.

Ein häufiger Fehler

Warnung

Viele glauben, die Zeile des Absturzes enthalte den Fehler. Oft wurde der falsche Wert schon früher gesetzt, und erst später kracht es. Gehen Sie mit bt zum Aufrufer und prüfen Sie mit print, wo der Wert zum ersten Mal falsch ist.

Über dieses Lab und seinen Quellcode: Lab für Compilerbau und Rechnerarchitektur: gcc, flex, bison und RISC-V in einer VM

Sie unterrichten eine Gruppe? Weisen Sie dieses Modul Ihren Studierenden zu, mit Handbuch für Lehrende, automatisch geprüften Aufgaben und einem Lab für jede Person.