![]() |
Institut für Angewandte Mathematik
|
![]() |
![]() |
Jeder der eine wenig C/C++ programmiert hat kennt den folgenden Fehler:
>./seg
Segmentation fault
Dieser wurde mit dem beiliegenden C Programm "seg" erzeugt. Dies soll im Folgenden unser Beispiel sein. Dieses Beispiel kann mit
> gcc -o seg seg.c
übersetzt werden.
Die Suche nach solchen Fehlern kann sehr langwierig und kompliziert sein, wenn man nicht die richtigen Hilfsmittel zu Verfügung hat. Das Mittel der Wahl ist hier ein sogennanter Debuger. Das ist ein Programm, dass es ermöglicht in einen Blick in ein laufendes Programm zu werfen und den Programmablauf nachzuvollziehen. Der Debuger unserer Wahl wird "dgb" sein.
Um dem Debuger einen Blick ins innere eines Programms zu ermölichen, muss zunächst das Programm mit sogennanten "Debugflags" versehen werden. Dies ermöglicht es später einem Stück Binärcode eine Programmzeile zuzuordnen. Dies kann der Compiler "gcc" während des übersetzens des Programms erledigen. Dazu ruft man ihn mit der Option "-g" auf. Also lautet die Zeile um das Programm mit "Debugflags" zu compilieren:
> gcc -g -o seg seg.c
Nun startet man den Debuger in dem man in der Shell
> gdb seg
eingibt. Der Debuger öffnet sich. Wenn man nun den Befehl "run" eingibt, wird das Programm gestartet und man erhältt folgende Ausgabe:
(gdb) run
Starting program:~/howto_cip/seg
Program received signal SIGSEGV, Segmentation fault.
0x0804840a in gen_segfault (n=5, ar=0x804a008) at seg.c:9
9 ar[i][j] = i*j;
Die drei letzen Zeilen sagen aus, dass das Programm mit einem "Segmentation fault" beendet wurde. Der Debuger konnte sogar ermitteln wo der Fehler auftrat und gibt die Quelldatei und die Zeile aus. Diese einzelne Zeile scheint zunächst wenig verdächtig. Da es sich um einen Array zugriff handelt, wäre es interressant den Wert der Laufvariablen i und j zu ermitteln. Dies kann mit den Befehlen
(gdb) print j
$1 = 0
(gdb) print i
$1 = 5
erreicht werden. Wenn wir nun die zugehörigen Schleifen:
for( i = 0; i <= n; ++i )
for( j = 0; j <= n ; ++j )
ar[i][j] = i*j;
betrachten ist der Fehler schnell identifiziert. Da wir nur eine 5x5 Matrix übergeben haben, dürffen wir natürlich nicht bis zum Index 5 auf die Matrix zugreifen. Daher ist es korrekt wenn wir stattdessen schreiben:
for( i = 0; i < n; ++i )
for( j = 0; j < n ; ++j )
ar[i][j] = i*j;
Abschliessend sei noch bemerkt, dass "gdb" einen größeren Befehlsumfang hat. Mit dem Befehl "help" kann man sich diese leicht selbst erschliessen.