Kurzanleitung für Debugger DDD / KDbg

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 !


Debugfähigen Code erzeugen

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


Programm in DDD laden

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.

1. Öffnen eines Programm

Ö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.

2. Breakpoint setzen/löschen

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.



Die wichtigsten Toolbox-Befehle:

DDD besitzt ein kleines Toolbox-Fenster zum Starten und Tracen (Programmverfolgung) von Code.



Die DDD-Fenster:

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.



Programm starten und schrittweise verfolgen

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.

Variablen und Strukturen untersuchen

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.


Literatur-Verweise

PC-Magazin Spezial 12/99
Linux für Einsteiger
Kapitel: DDD-Debugger S.88-91
19,80 DM


DDD 3.3.8 Homepage

http://www.gnu.org/software/ddd