next up previous contents Next:  Examiner les fichiers core. Up: Débogage avec gdb et Previous: Débogage avec gdb et   Table des matières  

23.2.1  gdb.

Le débogueur de GNU, gdb, remplace le débogueur db d'UNIX. [N.d.T: ddd est un autre programme très utile et graphique.] Le débogage d'un programme consiste à en réaliser l'exécution ligne par ligne, en vue de trouver les erreurs éventuelles. Utilisez la commande gcc -Wall -g -O0 -o wordspilt wordsplit.c pour recompiler le programme de la sous-section 23.1.9. L'option -g signifie ``support de débogage'' dans l'exécutable résultant et l'option -O0 désactive toute optimisation du compilateur (qui, sinon, parfois provoque un comportement déroutant). Pour réaliser l'exemple qui suit, créez deux fichiers d'essai readme.txt et readme2.txt contenant du texte. A présent, vous pouvez lancer gdb -q wordsplit. L'invite de gdb apparaît pour indiquer le début d'une session de débogage:

(gdb) 


Derrière cette invite, il est possible de passer de nombreuses commandes sous forme d'une seule lettre, de manière à contrôler l'exécution. La première de celle-ci est run qui exécute le programme comme s'il avait été démarré depuis un shell de manière classique:

(gdb) r 
Starting program: /home/src/wordsplit/wordsplit.c 
Usage: 
       wordsplit <filename> ... 
 
Programme exited with code 01 


Naturellement, nous pouvons passer des arguments en ligne de commande. Pour cela, on utilise la commande spéciale set args:

(gdb) set args readme1.txt readme2.txt  


La commande break est utilisée comme b [[<fichier>:]<ligne>[<fonction>]], et place un point d'arrêt (breakpoint) à un numéro de ligne ou au début d'une fonction:

(gdb) b main 
Breakpoint 1 at 0x8048796: file wordsplit.c, line 67. 


Un point d'arrêt interrompt l'exécution du programme. Dans le cas présent, le programme peut s'arrêter quand il entre dans la fonction main (c'est-à-dire tout au début). A présent, vous pouvez relancer le programme:

(gdb) r 
Starting program: /home/src/wordsplit/wordsplit readme.txt readme2.txt 
 
Breakpoint 1, main (argc=3, argv=0xbffff804) at wordsplit.c:67 
67          if (argc < 2) { 
(gdb) 


Comme indiqué, le programme s'arrête au début de main à la ligne 67.

Si vous vous intéressez à ce que contient une variable, vous pouvez faire usage de la commande print:

(gdb) p argc 
$1 = 3 
(gdb) p argv[1] 
$2 = 0xbffff988 "readme.txt" 


ce qui nous retourne la valeur d'argc et argv[1]. La commande list affiche les lignes voisines de la ligne courante:

(gdb) l 
63   int main (int argc, char *argv[]) 
64   { 
65       int i; 
66 
67       if (argc < 2) { 
68           printf ("Usage:\n\twordsplit <filename> ...\n"); 

69           exit (1); 
70       } 


La commande list peut aussi prendre un fichier en option et un numéro de ligne (ou même un nom de fonction):

(gdb) l wordsplit.c:1 
1        #include <stdlib.h>  
2        #include <stdio.h> 
3        #include <string.h> 
4 
5        void word_dump (char *filename) 
6        { 
7            int length_of_word; 
8            int amount_allocated; 


Ensuite, nous pouvons placer un point d'arrêt à un ligne donnée et utiliser la commande continue pour poursuivre l'exécution du programme:

(gdb) b wordsplit.c:48 
Breakpoint 2 at 0x804873e: file wordsplit.c, line 48. 
(gdb) c 
Continuing. 
Zaphod 
 
Breakpoint 2, word_dump (filename=0xbffff988 "readme.txt") at wordsplit.c:48 
48                 amount_allocated = 256; 


L'exécution s'arrête à la ligne 48. A ce stade, il est utile de lancer un backtrace. Ceci affiche la pile des fonctions qui ont été appelées pour atteindre la ligne courante, ce qui vous permet de tracer l'historique de l'exécution.

(gdb) bt 
#0   word_dump (filename=0xbffff988 "readme.txt") at wordsplit.c: 48 
#1   0x80487e0 in main (argc=3, argv=0xbffff814) at wordsplit.c:73 
#2   0x4003db65 in __libc_start_main (main=0x8048790 <main>, argc=3, ubp_av=0xbffff814, init=0x08048420 <_init>, 
     fini=0x804883c <_fini>, rtld_fini=0x4000df24 <dl_fini>, stack_end=0xbffff80c) at ../sysdeps/generic/libc-start.c:111 


La commande clear supprime les points d'arrêts de la ligne courante:

(gdb) clear  
Deleted breakpoint 2 


Les commandes les plus importantes pour le débogage sont next et step. La commande n exécute une seule ligne de code C à la fois:

(gdb) n 
49          q = realloc (q, amount_allocated); 
(gdb) n 
50          if (q == 0) { 
(gdb) n 
50          length_of_word = 0;  


Cette activité est appelée le steeping. La commande s est similaire à n mais elle traverse les fonctions sans s'arrêter ligne après ligne dans le code qu'elles contiennent. Pour apprécier la différence de comportement entre s et n, essayez ceci:

(gdb) set args readme.txt readme2.txt 
(gdb) b main 
Breakpoint 1 at 0x8048796: file wordsplit.c, line 67. 
(gdb) r 
Starting program: /home/src/wordsplit/wordsplit readme.txt readme2.txt 
 
Breakpoint 1, main (argc=3, argv=0xbffff814) at wordsplit.c:67 
67          if (argc < 2) { 
(gdb) n 
72          for (i = 1; i < argc; i++) { 
(gdb) n 
73          word_dump (argv[i]); 
(gdb) n 
Zaphod 
has 
two 
heads 
72          for (i = 1; i < argc; i++) { 
 
(gdb) s 
73          word_dump (argv[i]); 
(gdb) s 
word_dump (filename=0xbffff993 "readme2.txt") at wordsplit.c:13 
13          c = 0 
(gdb) s 
15          f = fopen (filename, "r"); 
(gdb) 


Un trait intéressant de gdb est sa capacité à être attaché à des programmes en cours. Essayez la séquence de commandes suivantes:

[root@cericon]# lpd 
[root@cericon]# ps awx | grep lpd 
28157?          S          0:00 lpd Waiting 
28160 pts/6     S          0:00 grep lpd 
[root@cericon]# gdb -q /usr/bin/lpd 
(no debugging symbols found)... 
(gdb) attach 28157 
Attaching to program: /usr/sbin/lpd, Pid 28157 
0x40178bfe in __select () from /lib/libc.so.6 
(gdb) 


Le démon lpd n'a pas été compilé avec le support de débogage, mais vous pouvez arrêter et déboguer n'importe quel processus de votre système. Essayez bt pour voir. A présent, libérez le processus avec:

(gdb) detach 
Detaching from program: /usr/sbin/lpd, Pid 28157  


Le débogueur fournit une importante quantité d'aide en ligne. La commande help peut être lancée à cette fin. Les pages d'info associées à la commande info gdb présente également un grand nombre de données qui ne seront pas couvertes ici.


next up previous contents Next:  Examiner les fichiers core. Up: Débogage avec gdb et Previous: Débogage avec gdb et   Table des matières  
1-01-2006