Website-Suche

GNU Debugger oder GDB: Ein leistungsstarkes Quellcode-Debugging-Tool für Linux-Programme


Ein Debugger spielt in jedem Softwareentwicklungssystem eine wichtige Rolle. Niemand kann auf einmal einen fehlerfreien Code schreiben. Im Laufe der Entwicklung treten Fehler auf, die zur weiteren Verbesserung behoben werden müssen. Ein Entwicklungssystem ist ohne einen Debugger unvollständig. In Anbetracht der Open-Source-Entwicklergemeinschaft ist GNU Debugger die beste Wahl. Es wird auch für die kommerzielle Softwareentwicklung auf UNIX-Plattformen verwendet.

Mit dem GNU Debugger, auch bekannt als gdb, können wir uns den Code ansehen, während er ausgeführt wird, oder sehen, was ein Programm gerade versucht hat, bevor es abstürzte. GDB hilft uns im Wesentlichen dabei, vier Hauptaufgaben zu erfüllen, um Fehler im Quellcode zu erkennen.

  1. Starten Sie das Programm und geben Sie Argumente an, die sich auf das allgemeine Verhalten auswirken können.
  2. Stoppen Sie das Programm unter bestimmten Bedingungen.
  3. Untersuchen Sie den Absturz oder den Zeitpunkt, an dem das Programm gestoppt wurde.
  4. Ändern Sie den Code und experimentieren Sie sofort mit dem geänderten Code.

Mit gdb können wir ohne großen Aufwand Programme debuggen, die in C und C++ geschrieben sind. Die Unterstützung für andere Programmiersprachen wie D, Modula-2, Fortran ist derzeit nur teilweise möglich.

Erste Schritte mit GNU Debugger oder GDB

GDB wird mit dem Befehl gdb aufgerufen. Bei der Eingabe von gdb werden einige Informationen zur Plattform angezeigt und Sie gelangen zur Eingabeaufforderung (gdb), wie unten gezeigt .

[root@fedora20 ~]# gdb
Beispielausgabe
GNU gdb (GDB) Fedora 7.6.50.20130731-19.fc20 
Copyright (C) 2013 Free Software Foundation, Inc. 
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 
This is free software: you are free to change and redistribute it. 
There is NO WARRANTY, to the extent permitted by law.  Type "show copying" 
and "show warranty" for details. 
This GDB was configured as "x86_64-redhat-linux-gnu". 
Type "show configuration" for configuration details. 
For bug reporting instructions, please see: 
<http://www.gnu.org/software/gdb/bugs/>. 
Find the GDB manual and other documentation resources online at: 
<http://www.gnu.org/software/gdb/documentation/>. 
For help, type "help". 
Type "apropos word" to search for commands related to "word". 
(gdb)

Geben Sie help list ein, um die verschiedenen in gdb verfügbaren Befehlsklassen anzuzeigen. Geben Sie help gefolgt von einem Klassennamen für eine Liste von Befehlen in dieser Klasse ein. Geben Sie help all ein, um die Liste aller Befehle anzuzeigen. Abkürzungen für Befehlsnamen sind zulässig, sofern sie eindeutig sind. Beispielsweise können Sie n anstelle von next oder c eingeben > für weiter und so weiter.

Am häufigsten verwendete GDB-Befehle

Häufig verwendete gdb-Befehle sind in der folgenden Tabelle aufgeführt. Diese Befehle müssen über die gdb-Eingabeaufforderung (gdb) verwendet werden.

Command

Beschreibung

run

Programmausführung starten

quit

gdb beenden

print expr

Ausdruck drucken, wobei expr auch ein Variablenname sein kann

next

Gehe zur nächsten Zeile

step

Gehen Sie in die nächste Zeile

continue

Weiter von der aktuellen Zeile bis zum Ende des Programms oder zum nächsten Haltepunkt

Beachten Sie den Unterschied zwischen den beiden Befehlen step und next. Der Befehl next geht nicht in die Funktion, wenn die nächste Zeile ein Funktionsaufruf ist. Der Befehl step hingegen kann in die Funktion hineingehen und sehen, was dort passiert.

Eine Beispielsitzung mit GDB

Betrachten Sie den folgenden Quellcode.


// sum.c
#include <stdio.h> 

int sum (int a, int b) { 
	int c; 
	c = a + b; 
	return c; 
} 

int main() { 
	int x, y, z; 
	printf("\nEnter the first number: "); 
	scanf("%d", &x); 
	printf("Enter the second number: "); 
	scanf("%d", &y); 
	z = sum (x, y); 
	printf("The sum is %d\n\n", z); 
	return 0; 
}

Um die Ausgabedatei zu debuggen, müssen wir sie wie folgt mit der Option -g für gcc kompilieren.

gcc -g sum.c -o sum

Die Ausgabedatei sum kann auf eine der beiden folgenden Arten an gdb angehängt werden:

1. Durch Angabe der Ausgabedatei als Argument für gdb.

gdb sum

2. Ausgabedatei in GDB mit dem Befehl file ausführen.

gdb
(gdb) file sum

Der Befehl list listet Zeilen in der Quellcodedatei auf und bewegt den Zeiger. Die erste Liste zeigt also die ersten 10 Zeilen an und die nächste Liste zeigt die nächsten 10 an und so weiter.

(gdb) list
1	#include <stdio.h>   
2	 
3	int sum (int a, int b) { 
4		int c; 
5		c = a + b; 
6		return c; 
7	} 
8	 
9	int main() { 
10		int x, y, z;

Um die Ausführung zu starten, geben Sie den Befehl run aus. Jetzt wird das Programm normal ausgeführt. Aber wir haben vergessen, zum Debuggen einige Haltepunkte in den Quellcode einzufügen, oder? Diese Haltepunkte können für Funktionen oder an bestimmten Zeilen angegeben werden.

(gdb) b main

Hinweis: Ich habe für break die Abkürzung b verwendet.

Nachdem der Haltepunkt in der Hauptfunktion festgelegt wurde, stoppt die erneute Ausführung des Programms in Zeile 11. Dasselbe kann umgesetzt werden, wenn die Zeilennummer zuvor bekannt ist.

(gdb) b sum.c:11

Gehen Sie nun mit den Befehlen next oder n schrittweise durch die Codezeilen. Es ist wichtig zu beachten, dass der Befehl next nicht in den Funktionscode eingeht, es sei denn, für die Funktion wird ein Haltepunkt festgelegt. Probieren wir jetzt den Befehl print aus. Legen Sie den Haltepunkt für die Funktionssumme wie unten beschrieben fest.

(gdb) b sum 
Breakpoint 1 at 0x4005aa: file sum.c, line 5. 
(gdb) r 
Starting program: /root/sum 

Enter the first number: 2 
Enter the second number: 3 

Breakpoint 1, sum (a=2, b=3) at sum.c:5 
5		c = a + b; 
(gdb) p a 
$1 = 2 
(gdb) p b 
$2 = 3
(gdb) c 
Continuing. 
The sum is 5 

[Inferior 1 (process 3444) exited normally]

Wenn das auszuführende Programm Befehlszeilenparameter erfordert, geben Sie diese zusammen mit dem Befehl run an.

(gdb) run   . . .

Gemeinsam genutzte Bibliotheksdateien, die dem aktuell ausgeführten Programm zugeordnet sind, können als aufgelistet werden.

(gdb) info share 
From                To                  Syms Read   Shared Object Library 
0x00000035a6000b10  0x00000035a6019c70  Yes         /lib64/ld-linux-x86-64.so.2 
0x00000035a641f560  0x00000035a6560bb4  Yes         /lib64/libc.so.6

Variablen ändern

GDB ist auch in der Lage, Variablen während der Programmausführung zu ändern. Probieren wir es aus. Wie oben erwähnt, setzen Sie den Haltepunkt in Zeile 16 und führen Sie das Programm aus.

(gdb) r 
Starting program: /root/sum 

Enter the first number: 1 
Enter the second number: 2 

Breakpoint 1, main ( ) at sum.c:16 
16		printf("The sum is %d\n\n", z); 
(gdb) set z=4 
(gdb) c 
Continuing. 
The sum is 4

Jetzt ist a=1, b=2 und das Ergebnis sollte z=3 sein. Aber hier haben wir das Endergebnis in der Hauptfunktion auf z=4 geändert. Auf diese Weise kann das Debuggen mithilfe von gdb erleichtert werden.

Haltepunkte aktivieren/deaktivieren

Um die Liste aller Haltepunkte zu erhalten, geben Sie info breakpoints ein.

(gdb) info breakpoints 
Num     Type           Disp Enb Address            What 
1       breakpoint     keep y   0x00000000004005c2 in main at sum.c:11

Hier gibt es nur einen Haltepunkt und zwar To. Aktiviert Deaktivieren Sie die Haltepunkte. Geben Sie die Haltepunktnummer zusammen mit dem Befehl disable an. Um es anschließend zu aktivieren, verwenden Sie den Befehl enable.

(gdb) disable 1 
(gdb) info breakpoints 
Num     Type           Disp Enb Address            What 
1       breakpoint     keep n   0x00000000004005c2 in main at sum.c:11

Sie können die Haltepunkte auch mit dem Befehl delete löschen.

Debuggen laufender Prozesse

In einem GNU/Linux-System laufen zahlreiche Prozesse im Hintergrund. Um einen laufenden Prozess zu debuggen, müssen wir zunächst die Prozess-ID dieses bestimmten Prozesses ermitteln. Der Befehl pidof gibt Ihnen die PID eines Prozesses.

pidof <process_name>

Jetzt müssen wir diese PID an GDB anhängen. Es gibt zwei Möglichkeiten.

1. Durch Angabe von pid zusammen mit gdb.

gdb -p <pid>

2. Verwenden des Befehls attach von gdb.

(gdb) attach <pid>

Das ist alles für den Moment. Dies sind nur die Grundlagen von gdb, um einen guten Einstieg in das Debuggen von Quellcode zu ermöglichen, und es geht um viel mehr als die oben erläuterten Dinge. Beispielsweise können wir mithilfe der Stack-Informationen, Umgebungsvariablen und vielem mehr debuggen. Versuchen Sie, mit all diesen Dingen herumzuspielen ...