
Größere Programme sind selten fehlerfrei. Um den Fehlern
nachzuspüren, setzen Profis sogenannte Debugger ein. Dies sind Programme
mit denen man Programme schrittweise testen kann. Dabei kann man im Quelltext
Haltepunkte markieren, um dort Variablen und Speicherbereiche zu analysieren.
Unter Linux ist der gdb (GNU-Debugger) im Einsatz. Er ist sehr leistungsstark, aber leider rein
textorientiert und kryptisch. Damit ein Normalsterblicher nicht an gdb
verzweifelt, werden sogenannte grafische gdb-Frontends eingesetzt, die
gdb-Befehle sehr schön aufbereiten.
Der mächtigste Linux-Debugger ist der DDD (Data
Display Debugger) . Er ist im SuSE-Linux
verfügbar (Serie xdev). Allerdings ist er recht speicherintensiv und nicht
immer einfach bedienen.
Sein kleinerer Bruder ist der kleine und flinke Debugger kdbg. Er reicht in vielen Fällen
völlig aus, alles andere ist ein Fall für DDD. Bevor man mit DDD beginnt,
sollte man unbedingt diesen kleinen Debugger einmal probieren !
Von Haus aus enthält ein Maschinenprogramm keinen
debugfähigen Code. Es sei denn, man liebt unkommentierten Maschinencode.
Um C++-Programme zu debuggen, muß der C++-Compiler eine Symboltabelle mit
Variablen und Zeileninformationen an den Code anhängen.
Mit der Compileroption -g weisen wir den GNU-Compiler an,
diese Symboltabelle an den Code anzuhängen.
Geben Sie den Befehl: g++ -g program.cpp -o
program ein
Starten Sie DDD unter X-Windows (z.B. im KDE-Desktop).
Sie finden das Programm im Verzeichnis /usr/bin/ddd. Am besten legen Sie DDD als Verknüpfung auf den
KDE-Desktop.

.
Hier ein Blick in
eine Debug-Sitzung des Baum-Teams.
Ein DDD-Fenster besteht meist aus 3 Fenstern untereinander. Oben ist das Data
Window für die Anzeigen von Variablen. In der Mitte ist das Quelltext-Fenster
und unten das gdb-Fenster für direkte Kommandos an den GNU-Debugger.
Zusätzlich gibt es noch ein Execution-Window für Programme im Textmodus,
um die Programm Ein-/Ausgaben vorzunehmen.
Öffnen Sie Ihr Programm mit dem Menü File und Open Program. Sollte
Ihr Programm aus mehreren Dateien bestehen, benutzen Sie zusätzlich Open
Source. Nun erscheint Ihr Quelltext im Programmfenster.
Um ein Programm zu testen, muß man mindestens einen Breakpoint
definieren. An diesem Breakpoint wird dann DDD anhalten und man kann mit den
Tests beginnen. Fahren Sie mit der Maus an den Beginn einer Programmzeile und
drücken Sie die rechte Maustaste.
Breakpoint setzen mit : Set Breakpoint
Ebenso können Sie einen Breakpunkt über das Symbol
Break setzen, es wird dann die aktuelle Cursorzeile
für den Breakpunkt benutzt. Setzt man den Cursor auf den Breakpunkt, so
erscheint dann ein Symbol Clear mit dem
er dann wieder gelöscht werden kann.

Es erscheint ein kleines Stop-Symbol. Dieses Symbol können Sie sogar
mit den linken Maustaste nachträglich auf eine andere Programmzeile
schieben.
Zum Löschen eines Breakpoints klicken Sie diesen mit der rechten Maustaste
an.
Breakpoint löschen mit : Delete
Breakpoint
Breakpoint desaktivieren : Disable
Breakpoint

Breakpoint mit Bedingungen versehen : Properties

Hier kann man z.B. festlegen, daß das Programm nur anhalten soll, wenn
die Variable i größer als 8 ist. Ignore
count legt fest, wie oft der Breakpoint passiert
werden, soll ohne zu stoppen.
DDD besitzt ein kleines Toolbox-Fenster zum Starten und
Tracen (Programmverfolgung) von Code.
DDD besitzt max. 5 verschiedene Fenstertypen, die im
Menü View aktiviert werden können.
Man beachte, daß man bei Programm-Eingaben per Maus ins
Execution-Fenster bzw. in das eigene X-basierte Programm wechseln muß. Es
geht in der KDE-Oberfläche auch mit der Tastenkombination ALT-TAB.
Das glorreiche Programm soll die Prüfsumme des
Namens 'Billy Knilly' ermitteln. Dabei werden in der Variablen
checksumme die einzelnen
ASCII-Codes der Buchstaben addiert.

Das Bild zeigt den Quelltext im Editor kwrite.
Mit Run starten
Sie Ihr Programm. Es bleibt dann an dem gewünschten Breakpoint bei
i++ stehen. Ein
grüner Pfeil zeigt die aktuelle Programmzeile an.

Der Befehl i++ wird allerdings erst beim nächsten Step-Befehl ausgeführt. Somit hat i immer noch den Wert 0. Im obigen Data-Fenster habe ich bereits einige Variablen anzeigen lassen.
Die einfachste Methode einen Variableninhalt zu sehen,
ist einfach den Mauszeiger auf die Variable zu schieben und ein wenig zu
warten. Dann wird neben der Variable ihr Wert direkt angezeigt. Dies ist aber
nur eine kurzfristige Methode. Im Bild 1 wird die Variable c2 angezeigt. Sie hat den Wert
91, was dem ASCII-Zeichen geschweifte Klammer_zu entspricht.
Besser man legt sich die Variable im Data-Fenster ab. Dazu markiert man den
Variablennamen im Quelltext mit der linken Maustaste und drückt dann die
rechte Maustaste. Dann erscheint ein kleines Menü.

Mit dem Befehl Display name erscheint die String-Variable name im Display Fenster. Mit dem
Befehl Display *name
erscheint der Inhalt auf den der Zeiger name zeigt (in unserem auf der
große 'B' ´von 'Billy Knilly').
Sämtliche Symbole können im Data-Fenster beliebig verschoben werden.
Das Data-Fenster kann mit dem kleinen grauen Rechteckknopf an rechten unten
Fensterrand beliebig vergrößert werden. Dazu ziehen Sie das Fenster
mit der linken Maustaste auf.
Wie Sie sehen, habe ich mit dem Step-Befehl bereits die
nächste Programmzeile erreicht. Nach i++ springt das Programm
wieder zum Schleifenkopf der while-Schleife.
Der Wert von i und
name[i] haben sich
geändert. Dies zeigt DDD mit beige hintergelegten Variablen an. Wir sind
also beim 2. Buchstaben von 'Billy Knilly' angelangt. Die Variable
checksumme ist noch 66.
Dies ist der ASCII-Code für das große 'B'.
DDD ist in der Lage sehr komplexe Datenstrukturen und Zeigerkonstrukte
darstellen. Dies sieht man z.B. im Bild 1, wo die Strukturvariable s[0]
dargestellt ist. Selbstverständlich kann man auch zur Laufzeit
Variablenwerte ändern. Dazu klickt man auf eine Variable im Data-Fenster
mit der rechten Maustaste und setzt den Wert mit Set
Value .
Komplexere Ausdrücke können Sie im Eingabefeld oben links per Hand
eingeben und per Display-Icon im Data-Fenster sichtbar machen. Im Bild 1 haben
wir den Wert von *(cstack-3) eingespiegelt.

Im letzten Fenster habe den Breakpoint mit der linken Maustaste auf printf
verschoben. Danach habe den Toolbox-Befehl Cont ausgeführt, der dann
beim Breakpoint anhält. Das Programm hat dabei die While-Schleife abgearbeitet
und die Checksumme von 'Billy Knilly' gebildet.
Mit dem Menü Data und dem Menüpunkt Display Local Variables habe
ich alle lokalen Variablen des Hauptprogramms main im Data-Fenster ausgegeben.
Möchte man eine Variable aus dem Data-Fenster löschen, so klickt man
sie im Data-Fenster an und klickt danach auf das Undisplay-Icon.
Der Menüpunkt Status/Backtrace zeigt in einem komplexeren Programm die aktuelle Unterprogrammschachtelung
an. Man sieht man leicht, welche Unterprogrammruf bis zum Breakpoint erfolgt
sind.
Tip:
Mit dem Step-Befehl
werden auch Bibliotheksfunktionen, wie strcmp, strcpy und auch new, zeilenweise
abgearbeitet. Normalweiser will man aber die innere Funktion solcher Bibliotheksfunktionen
nicht wissen. Steht also ein solcher Befehl an, sollte man immer den Next-Befehl
verwenden. Dies spart das nervige Tracen innerhalb dieser
Funktionen.
KDbg - Debugger
KDbg 1.9.6 ist ein kleiner, aber feiner Debugger. Er ist nicht so mächtig, wie DDD, aber reicht in vielen Fällen völlig aus. Nach dem Laden des Programms und evtl. zusätzlicher Quellcode-Dateien sucht man sich die Stelle an der man einen Breakpoint setzen möchte.
Verwenden sie Version 1.9.6 oder 1.2.10 in SuSE 9.1. Die mitgelieferte Version 1.2.9 ist fehlerhaft (libthread-db.so.1-Bug)) !
Am bequemsten geht dies mit der Maus. Dazu klickt man einfach den linken der Rand der gewünschten Programmzeile an. Das Programm kann man entweder über die Symbolleiste debuggen oder per Tastatur.

Wichtige Tasten in KDbg:
F5 : Programm starten
F6: An Unterprogrammende springen
F8: Einzelschritt vorwärts
F9: Breakpoint setzen/löschen
F10: Unterprogramm überspringen
Für lokale Variablen, Unterprogrammstack und Ausdrücke gibt es frei
positionierbare Fenster. Zusätzlich gibt es ein Terminalfenster für
Textaus- und eingaben.In unserem Bild sehen wir das Quellcodefenster mit einem
Breakpunkt (roter Kreis). Der grüne Pfeil markiert den aktuellen Befehl.
Zusätzlich sehen wir die lokalen Variablen und den Stack in einem Extrafenster.
Lokale Variableninhalte werden aber auch angezeigt, wenn man den Mauszeiger
im Quellcode auf sie schiebt.
Wir sind inzwischen komplett auf den KDbg umgestiegen, da er schneller und handlicher als der DDD ist.
PC-Magazin Spezial 12/99
Linux für Einsteiger
Kapitel: DDD-Debugger S.88-91
19,80 DM