Willemers Informatik-Ecke
Kontrollierter Ablauf von Programmen
Ein Debugger ist ein Programm, das den Programmierer dabei unterstützen soll,
Programmfehler zu finden. Diese Fehler werden als Bug (engl. für Wanze oder
Käfer) bezeichnet. Entsprechend ist der Debugger ein "Entwanzer".
Ein Debugger lässt das zu untersuchende Programm unter seiner Kontrolle
ablaufen. Man kann das Programm an bestimmten Punkten stoppen lassen und im
Einzelschritt verfolgen. Dabei lassen sich Variableninhalte anzeigen.
Damit das erzeugte Programm dem Debugger etwas zu sagen hat, muss es mit dem
Flag -g compiliert worden sein.
Start in den Tod
Ist das Problem ein Programmabsturz, so wird man typischerweise das Programm
im Debugger einfach starten und in die Situation des Zusammenbruchs laufen
lassen. Sobald das Programm zusammenbricht, fängt der Debugger es auf und
meldet, an welcher Stelle der frühe Tod zu vermelden war.
Breakpoints bis zum Übelwerden
Schwieriger ist es schon, wenn das Programm durchaus läuft, aber die
Ergebnisse nicht die erwarteten sind. In solchen Fällen wird man vor dem
Start des Programms an den Stellen, wo man Probleme vermutet jeweils einen
Breakpoint setzen. Nach dem Start des Programmes wird dieses normal laufen,
bis es einen Breakpoint erreicht. Dort wird das Programm anhalten. Man kann
sich die Variablen anzeigen lassen und Schritt für Schritt weitergehen.
Prozesse kapern
Moderne Debugger sind sogar in der Lage, einen bereits laufenden Prozess
unter ihre Kontrolle zu bekommen. Das ist besonders deswegen interessant,
weil es ansonsten gar keine Möglichkeit gäbe, beispielsweise Dämonen zu
überwachen.
Analyse des core dump
Der Debugger ist bei der Analyse eines core dump hilfreich. Ein core dump
entsteht dann, wenn das Programm vom Betriebssystem die Arbeitserlaubnis
entzogen bekommen hat, weil es beispielsweise versucht hat, in Speicherbereiche
zu greifen, die ihm nicht gehören. Dabei enthält der core dump den Abzug des
Speichers des Prozesses in jenem Moment. Ein Debugger kann mit Hilfe dieser
Datei feststellen, an welcher Zeile der Absturz erfolgt ist und welche
Funktionen das Programm durchlaufen wurden, um an diese Stelle zu kommen.
Da der Debugger auch in der Lage ist, die Variableninhalte anzuzeigen, kann
man mit dieser Information recht gut feststellen, was die Ursache war.
Grafische Oberfläche
Für die Debugger gibt es teilweise auch grafische Oberflächen. Vom Prinzip
her arbeiten diese natürlich gleich, sind aber teilweise etwas leichtfüßiger
zu bedienen.
dbx
Der Debugger dbx läuft auf diversen Plattformen wie Sun oder AIX.
Beim Aufruf des Debuggers kann als Parameter ein ausführbares Programm
angegeben werden. Als dritter Parameter kann noch ein core angegeben werden.
dbx Programm
dbx Programm core
|
Programm ist das zu untersuchende Programm. core heißt die Datei,
die UNIX bei einem Programmzusammenbruch erzeugt. Dieser so genannte coredump
enthält den Inhalt des Speichers zum Zeitpunkt des Zusammenbruchs und
ermöglicht mit Hilfe des Debuggers die Analyse, wo der Absturz stattfand.
Innerhalb des Debuggers können die folgenden Befehle gegeben werden:
- where
-
zeigt den Stack der aufgerufenen Funktionen an.
Das funktioniert auch, wenn man einen core dump geladen hat.
Damit wissen Sie, wo das Programm zusammengebrochen ist.
- stop
-
Mit dem Befehl stop werden Breakpoints gesetzt. Dabei gibt es
zwei Formen.
stop at erwartet als Parameter eine Zeile und stop in
eine Funktion.
- delete
-
Der Befehl delete entfernt einen Breakpoint.
- run
-
run startet das geladene Programm.
- cont
-
cont setzt den
Lauf fort, wenn das Programm durch einen Breakpoint gestoppt worden war.
- step
-
Durchläuft schrittweise das Programm und zeigt immer die aktuelle
Sourcecodezeile
- display variable
-
Beobachtet Variablen. Nach jedem step wird die Variable mit ihrem
neuen Wert angezeigt
- quit
-
Verlasse den Debugger
adb (System V)
adb ist ein älterer Debugger, der bei System V mitgeliefert wird.
Der Debugger verwendet Buchstaben als Kommandos.
Auch mit dem adb läßt sich ein coredump analysieren. Der Aufruf ist wie bei
anderen Debuggern mit dem Programm und dem core dump als Parameter.
Anschließend wird mit c die Liste der Aufrufe erzeugt und mit q kann der
Debugger verlassen werden.
Einen Breakpoint setzt man, indem man zunächst die Adresse, an
der der Breakpoint sein soll nennt, dann ein Doppelpunkt und das Kommando
b. Die Adresse kann ein Funktionsname mit einem Offset oder eine hexadezimale
Position sein. Beispiel:
Der Befehl b allein zeigt die Liste der definierten Haltepunkte an.
Mit dem Befehl r wird das geladene Programm gestartet.
Das Programm läuft dann bis zum nächsten Haltepunkt. Dort kann man mit c
weiterlaufen, mit s schrittweise weitergehen oder mit k stoppen.
Kommando | Wirkung |
b | zeige die break points |
r | starte das Programm |
c | weiterlaufen (continue), bei core dump: Anzeige der Aufruffolge |
s | schrittweise ablaufen lassen |
k | stoppe das Programm |
gdb GNU debug
Der GNU Debugger gdb wird normalerweise mit dem zu untersuchenden
Programm als Parameter gestartet. Als weiterer Parameter kann auch hier ein
core dump angegeben werden.
Laufende Prozesse kapern
gdb kann ein laufendes Programm unter seine Fittiche nehmen.
Dazu wird der gdb gestartet und der Befehl at oder
attach abgesetzt.
Der Prozess wird gestoppt und mit dem gdb verbunden.
Starten und Stoppen
Im Debugger gibt es diverse Befehle. Mit run kann man das geladene
Programm starten, mit dem Befehl kill wieder stoppen. Mit
quit kann man den Debugger verlassen.
Breakpoint setzen
Um an den kritischen Stellen den Programmablauf unterbrechen zu können, muss
man einen Breakpoint setzen. Der Befehl break erwartet als Parameter
die Zeilenzahl im Listing oder ein Funktionsname. Die Zeilennummer ermittelt
man durch Auflisten des Programms, was gdb durch den Befehl
list ausführt.
Schritt für Schritt
Hat man den Breakpoint erreicht, kann man mit den Befehlen step oder
next Schritt für Schritt das Programm durchlaufen. Dabei wird
step in aufgerufene Funktionen hinuntersteigen, was next
nicht tut. Mit continue lässt man das Programm weiterlaufen.
Variablen durchleuchten
Will man einen Blick auf Variablen werfen, ist print dazu der
einfachste Befehl. Mit dem Befehl watch kann man Variablen unter
Bewachung stellen. Dieser Befehl zeigt den Inhalt, sobald er sich ändert.
Kommando | Aktion |
quit | Debugger verlassen |
run | das geladene Programm starten |
kill | stoppen des laufenden Programms |
print Variable | Inhalt der Variablen anzeigen |
watch Variable | Variable beobachten |
list | zeigt einen Ausschnitt aus dem Sourcelisting |
break Funktionsname | setzen eines Breakpoints |
break Zeilennummer | setzen eines Breakpoints |
clear Funktionsname | löscht einen Breakpoint |
clear Zeilennummer | löscht einen Breakpoint |
next | eine Zeile weitergehen |
step | eine Zeile weiter und ggf. in eine Funktion hinein |
continue | fortsetzen des angehaltenen Prozesses |