Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort
Über die Autoren
Über dieses Buch
Linux vs. BSD
1 Der Kernel
2 Die Grundlagen aus Anwendersicht
3 Die Shell
4 Reguläre Ausdrücke
5 Tools zur Dateibearbeitung
6 Die Editoren
7 Shellskriptprogrammierung
8 Benutzerverwaltung
9 Grundlegende Verwaltungsaufgaben
10 Netzwerk-Grundlagen
11 Anwendersoftware für das Netzwerk
12 Netzwerkdienste
13 Mailserver unter Linux
14 LAMP
15 DNS-Server
16 Secure Shell
17 Die grafische Oberfläche
18 Window-Manager und Desktops
19 X11-Programme
20 Multimedia und Spiele
21 Softwareentwicklung
22 Crashkurs in C und Perl
23 Sicherheit
24 Prozesse und IPC
25 Bootstrap und Shutdown
26 Dateisysteme
27 Virtualisierung und Emulatoren
A Die Installation
B Lösungen zu den einzelnen Aufgaben
C Kommandoreferenz
D X11-InputDevices
E MBR
F Die Buch-DVDs
G Glossar
H Literatur

Download:
- ZIP, ca. 6,3 MB
Buch bestellen
Ihre Meinung?

Spacer
 <<   zurück
Linux von Johannes Plötner, Steffen Wendzel
Das distributionsunabhängige Handbuch
Buch: Linux

Linux
2., aktualisierte und erweiterte Auflage
1119 S., 39,90 Euro
Galileo Computing
ISBN 978-3-8362-1090-4
gp 21 Softwareentwicklung
  gp 21.1 Interpreter und Compiler
    gp 21.1.1 C und C++
    gp 21.1.2 Perl
    gp 21.1.3 Java
    gp 21.1.4 Tcl
    gp 21.1.5 Was es sonst noch gibt
  gp 21.2 Shared Libraries
    gp 21.2.1 Vorteile der Shared Libraries
    gp 21.2.2 Statisches Linken
    gp 21.2.3 Die Dateien
  gp 21.3 Debugging
    gp 21.3.1 Vorbereitung
    gp 21.3.2 Konsolenarbeit
    gp 21.3.3 ddd
  gp 21.4 Profiling
    gp 21.4.1 Compileroption
    gp 21.4.2 gprof verwenden
    gp 21.4.3 Profiling-Daten lesen
  gp 21.5 Tracing
  gp 21.6 Hilfe beim Finden von Bugs
    gp 21.6.1 ProPolice
    gp 21.6.2 flawfinder und RATS
    gp 21.6.3 Electric Fence
  gp 21.7 Integrierte Entwicklungsumgebungen
  gp 21.8 make
    gp 21.8.1 Makefile
    gp 21.8.2 Makefile-Makros
    gp 21.8.3 Shell-Variablen in Makefiles
    gp 21.8.4 Einzelne Targets übersetzen
    gp 21.8.5 Spezielle Targets
    gp 21.8.6 Tipps im Umgang mit make
  gp 21.9 Die GNU Autotools
  gp 21.10 lex/flex und yacc/bison
    gp 21.10.1 flex grundlegend anwenden
    gp 21.10.2 bison/yacc grundlegend anwenden
  gp 21.11 Unix-Software veröffentlichen
    gp 21.11.1 Wichtige Dateien
  gp 21.12 Manpages erstellen
    gp 21.12.1 groff nutzen
    gp 21.12.2 Die Manpage installieren
  gp 21.13 Versionsmanagement
    gp 21.13.1 CVS
    gp 21.13.2 Subversion
  gp 21.14 Wichtige Bibliotheken
    gp 21.14.1 Entwicklung grafischer Oberflächen
    gp 21.14.2 Weitere Bibliotheken
  gp 21.15 Zusammenfassung
  gp 21.16 Aufgaben


Galileo Computing

21.3 Debugging  downtop

Ein sehr wichtiges Werkzeug in der Softwareentwicklung stellt der Debugger dar. Jede gute Entwicklungsumgebung beinhaltet entweder selbst einen Debugger (das ist beispielsweise bei Microsofts Visual-Studio/.NET der Fall) oder greift auf einen externen Debugger zurück (etwa Kdevelop unter Linux).

Ein Debugger hat dabei die Aufgabe, das Fehlverhalten von Programmen für den Entwickler auffindbar zu machen. Dabei kann Programmanweisung für Programmanweisung einzeln abgelaufen werden, während man parallel beispielsweise den Inhalt diverser Variablen im Blick behält.

Wir werden uns in diesem Buch mit dem mächtigsten freien Unix-Debugger auseinandersetzen: dem GNU-Debugger. Der GNU-Debugger gdb ist eigentlich auf jedem Linux- und BSD-System vorhanden und aufgrund seiner Verfügbarkeit auf diversen Plattformen und seines großen Funktionsumfanges äußerst beliebt.

Leider schrecken viele Entwickler trotzdem vor diesem Debugger zurück, da seine Anwendung (ohne Zuhilfename von Zusatztools) auf die Konsole beschränkt ist und alle Befehle von Hand angegeben werden müssen. Doch auch dafür gibt es Lösungen, etwa das grafische Fontend xxgdb oder ddd.

Unsere Herangehensweise an den gdb gestaltet sich nun so, dass wir zunächst eine Einführung in das Debuggen mit dem gdb auf der Konsolen-Ebene geben und anschließend auf ddd zu sprechen kommen, der Ihnen bereits mehr Komfort bietet und einfacher zu bedienen ist.


Galileo Computing

21.3.1 Vorbereitung  downtop

In diesem Kapitel werden wir ein Beispielprogramm, das mit einem Fehler versehen ist, als Debugging-Grundlage verwenden. Sein Listing sehen Sie hier:

#include <stdio.h> 
#include <string.h> 
 
int main(int argc, char *argv[]) 
{ 
   char a[]="abcdefghijklmnopqrstuvwxyz"; 
 
   strcpy(a+26, a); 
 
   return 0; 
}

Listing 21.15    sample.c

Unser Programm nennt sich sample. Normalerweise würde man es durch einen Aufruf von gcc -o sample sample.c übersetzen, doch reicht dies nicht aus, um komfortabel mit dem GNU-Debugger zu arbeiten. Dazu muss man gcc die Compiler-Option -g übergeben. Der Aufruf gestaltet sich also folgendermaßen: gcc -g -o sample sample.c

Führt man sample aus, erhält man, wie zu erwarten, eine Zugriffsverletzung im Speicher. In diesem Fall erstellen Unix-Systeme einen so genannten Coredump. Dies ist eine Datei, deren Name sich aus dem Programmnamen und der Endung ».core« zusammensetzt. Diese Datei wird beim Debuggen verwendet, um die Absturzstelle im Programm aufzuspüren.

$ ./sample 
Segmentation fault (core dumped) 
$ ls 
sample   sample.c   sample.core

Listing 21.16    sample


Galileo Computing

21.3.2 Konsolenarbeit  downtop

Nun werden wir uns zunächst auf der blanken Konsole bewegen und einige Grundlagen des gdb erlernen. Dazu ruft man gdb mit der Binärdatei und der Core-Datei als Argumente auf. Nachdem die Startmeldungen erschienen sind, teilt uns gdb auch gleich die Fehlerquelle mit, bei der die Speicherzugriffsverletzung stattfand: nämlich während eines Aufrufs der C-Libary-Funktion strcpy.

$ gdb sample sample.core 
GNU gdb 6.1 
Copyright 2004 Free Software Foundation, Inc. 
(...) 
This GDB was configured as "i386-unknown-openbsd3.6" 
Core was generated by `sample'. 
Program terminated with signal 11, Segmentation fault. 
Reading symbols from /usr/lib/libc.so.34.2...done. 
Loaded symbols for /usr/lib/libc.so.34.2 
Reading symbols from /usr/libexec/ld.so...done. 
Loaded symbols for /usr/libexec/ld.so 
#0  0x047ad4fb in strcpy () from /usr/lib/libc.so.34.2 
(gdb)

Listing 21.17    gdb starten

run und kill

Würden wir das Programm einfach durchlaufen lassen (gestartet wird mit dem Befehl run), würde sich uns die gleiche Information zeigen.

Ein Programm in der Ausführung lässt sich durch den Befehl kill abbrechen.

(gdb) run 
Starting program: /home/cdp_xe/test/sample 
 
Program received signal SIGSEGV, Segmentation fault. 
0x000bc523 in strcpy () from /usr/lib/libc.so.34.2

Listing 21.18    sample durchlaufen lassen

list

Möchte man sich nun den Source-Code des Programms ansehen, ruft man einfach den Befehl list auf. Dabei wird wahrscheinlich nicht gleich der gesamte Quelltext angezeigt. Durch mehrmaliges Betätigen der Return-Taste werden weitere Zeilen inklusive deren Zeilennummern angezeigt. Wenn alle Zeilen durchlaufen wurden, bekommen Sie eine entsprechende Meldung.

Breakpoints

Möchte man nun einen Breakpoint setzen, ist es von großem Vorteil, die Zeilennummern zu kennen, die man, wie Sie ja nun wissen, via list herausbekommt. Dabei verwendet man den Befehl break, der als Parameter die Nummer der Zeile übergeben bekommt, in der ein Breakpoint gesetzt werden soll.

Da fast jedes Softwareprojekt aus mehreren Quelldateien besteht, reicht es natürlich nicht aus, wenn man irgendeine Zeilennummer für einen Breakpoint angeben kann. Um zusätzlich die Quelldatei anzugeben, wird der Dateiname einfach zusätzlich bei break übergeben: break x.c:7.

(gdb) list 
1       #include <stdio.h> 
2       #include <string.h> 
3 
4       int main(int argc, char *argv[]) 
5       { 
6          char a[]="abcdefghijklmnopqrstuvwxyz"; 
7 
8          strcpy(a+26, a); 
9 
10         return 0; 
(gdb) 
11      } 
(gdb) 
Line number 12 out of range; sample.c has 11 lines. 
(gdb) break 7 
Breakpoint 1 at 0x1c0005fd: file sample.c, line 7.

Listing 21.19    break

Unser sample-Programm wird bei der Ausführung also nun in Zeile 7 angehalten. Da wir wissen, dass an der Speicherstelle a+26 nicht genug Platz für den Buffer-Inhalt von a sein wird, können wir – nachdem wir das Programm durch run bis zu dieser Position haben laufen lassen – den Wert von a so verändern, dass a nur noch das String-Terminierungszeichen \0 beinhaltet.

Würde nun also \0 an a+26 (dort steht sowieso ein \0) kopiert werden, würde das keine Speicherzugriffsverletzung hervorrufen, und das Programm würde normal beendet werden.

set

Der Wert einer Variable wird mit dem Befehl set verändert:

(gdb) run 
Starting program: /home/cdp_xe/test/sample 
 
Breakpoint 1, main (argc=1, argv=0xcfbf33e0) at 
sample.c:8 
8          strcpy(a+26, a); 
(gdb) set variable a = "\0"

Listing 21.20    Den Wert einer Variable anpassen

step und cont

Nun möchte man natürlich auch testen, ob die weitere Ausführung des Programms funktioniert. Dabei kann man entweder alle weiteren Anweisungen bis zum Programmende bzw. bis zum nächsten Breakpoint automatisch ablaufen lassen (was mit dem Befehl cont erreicht wird) oder auch schrittweise vorgehen, wobei jeweils nur eine Anweisung ausgeführt wird. Dazu verwendet man den Befehl step.

(gdb) step 
10         return 0; 
(gdb) step 
11      } 
(gdb) step 
0x1c0004c1 in ___start () 
(gdb) step 
Single stepping until exit from function ___start, 
which has no line number information. 
 
Program exited normally.

Listing 21.21    step

Variablen abfragen

Möchte man hingegen beim Ablauf des Programms den Wert einer Variablen abfragen, ist auch dies kein Problem. Der Name der Variable wird dazu einfach an den Befehl print übergeben.

(gdb) print a 
$1 = "abcdefghijklmnopqrstuvwxyz" 
(gdb) print argc 
$3 = 1 
(gdb) print argv 
$4 = (char **) 0xcfbfb410 
(gdb) print argv[0] 
$5 = 0xcfbfb614 "/home/cdp_xe/test/sample"

Listing 21.22    print a

help

Der GNU-Debugger unterstützt noch zahlreiche weitere Funktionen, auf die wir allerdings nicht alle im Einzelnen eingehen können. Daher verweisen wir auf die interne Hilfe-Funktion des Debuggers, die man, wie könnte es anders sein, mit dem Befehl help aufruft.

Weitere Informationen zum gdb in ausführlicherer Form erhalten Sie über die Info-Seite des Debuggers: info gdb.


Galileo Computing

21.3.3 ddd  toptop

Für den Fall, dass man nicht alle gdb-Befehle direkt eingeben möchte, kann man ein Fontend zu Hilfe nehmen. Dabei gibt es verschiedene Fontends, beispielsweise ncurses-basiert für die Konsole und diverse X11-Varianten, etwa den veralteten xxgdb. Wir werden uns mit einem sehr leistungsstarken gdb-basierten X11-Debugger, dem Data Display Debugger (ddd) beschäftigen.

Der ddd ist ein vergleichsweise einfach zu verwendender Debugger mit einigen sehr interessanten Features. Entwickelt wurde der ddd an der technischen Universität Braunschweig, und er unterstützt neben C und C++ auch Fortran, Ada und einige weitere Sprachen.

Sie müssen den ddd übrigens nicht zwangsläufig in Verbindung mit dem gdb verwenden. Es können über die entsprechenden Optionen auch andere Debugger, etwa JDB, Ladebug, perldebug, wdb, xdb oder PYDB verwendet werden. Außerdem kann der ddd auch remote debuggen.

Start

Gestartet wird der ddd über den Aufruf des Kommandos »ddd« und Angabe der Programmdatei des zu debuggenden Programms.

Bedienung

Die Bedienung des ddd ist recht intuitiv, empfehlenswert ist es, zu Beginn auch die Tipps zu lesen, die beim Start des Tools angezeigt werden.

Erwähnenswert ist vor allen Dingen die Fähigkeit, die Strukturen des Programms grafisch hervorzuheben. Dazu klickt man eine Variable während der Laufzeit mit der rechten Maustaste an (am besten setzt man sich hierzu irgendwo Breakpoints) und klickt auf Display bzw. Display * für Pointer.

Abbildung 21.2    ddd zeigt Strukturen an.

Analog dazu kann man natürlich auch ganz einfach den gdb-Befehl graph display verwenden. Um beispielsweise den Inhalt der Variable char *Q zu überwachen, müsste der folgende Befehl eingegeben werden:

(gdb) graph display *Q

Listing 21.23    *Q anzeigen lassen

Einzelne Werte der Strukturen lassen sich so ohne Aufwand und einfach überwachen und entweder direkt mit dem gdb-Befehl oder per Mausklick anpassen. Wenn Sie also mit den gdb-Befehlen auf Kriegsfuß stehen, ist dies kein Problem.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.






 <<   zurück
  
  Zum Katalog
Zum Katalog: Linux






 Linux
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


Zum Katalog: Einstieg in Linux






 Einstieg in Linux


Zum Katalog: Debian GNU/Linux






 Debian GNU/Linux


Zum Katalog: Ubuntu GNU/Linux






 Ubuntu GNU/Linux


Zum Katalog: Shell-Programmierung






 Shell-Programmierung


Zum Katalog: Linux-UNIX-Programmierung






 Linux-UNIX-
 Programmierung


Zum Katalog: Praxisbuch Netzwerk-Sicherheit






 Praxisbuch
 Netzwerk-Sicherheit


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Galileo Press 2008
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de