gdb est un debugger symbolique, c'est-à-dire un utilitaire permettant de contrôler le déroulement de programmes C, C++, Pascal ou Fortran. gdb permet (entre autres) de mettre des points d'arrêt dans un programme, de visualiser l'état de sa pile d'exécution ou de ses variables, de calculer des expressions, d'appeler interactivement des fonctions, etc.
xxgdb est une interface graphique qui facilite l'utilisation de gdb sous X-Window. ddd est une autre variante, plus évoluée.
Enfin gdb peut être lancé depuis Emacs via le menu "Tools" ou en tapant sous emacs la commande suivante :
ESC-X gdbDe même, on peut lancer la compilation via le menu "Tools" ou au moyen de la commande :
ESC-X compile
Créer un nouveau répertoire et y copier les fichiers suivants :
Les programmes C doivent être compilés avec le compilateur gcc avec l'option -g pour pouvoir être débuggés par gdb. Si on utilise un Makefile (comme c'est le cas ici), il faut que la macro CFLAGS contienne l'option -g.
Compiler les fichiers et créer l'exécutable en tapant la commande : make
pour lancer le débogueur tapez dans le Terminal :
xxgdb nom-du-programme-à-debugger ou, sinon gdb nom-du-programme-à-debugger
Si vous avez lancé xxgdb vous verrez apparaître sur l'écran une fenêtre xxgdb qui comprend deux ou trois zones de texte:
On peut alors utiliser xxgdb de deux manières:
Pour lancer l'exécution du programme taper:
run arguments-du-programmeou cliquer sur le bouton run (si le programme n'a pas d'argument)
gdb exécute alors le programme comme s'il avait été lancé normalement. L'exécution se poursuit jusqu'à la fin du programme sauf:
Tant que le programme "tourne", il n'est pas possible d'entrer de nouvelles commandes gdb (celles-ci ne seront effectuées que lorsque le programme s'arrêtera). gdb est alors en mode exécution. La seule façon de revenir en mode commande pendant l'exécution d'un programme est de taper ^C.
Les points d'arrêt servent à interrompre l'exécution et à revenir au mode commande à un endroit donné du programme.
Pour s'arrêter au debut d'une fonction, faire :
break nom-de-la-fonction
Pour s'arrêter dans le corps d'une fonction faire:
break numéro-de-ligne
L'exécution sera alors interrompue juste avant cette ligne.
On peut :
Dans les deux cas un marqueur s'affiche alors dans la fenêtre source pour signaler la présence d'un point d'arrêt.
Exemple : Mettre un point d'arrêt au début de la fonction Choix puis relancer l'exécution du programme depuis le debut en cliquant sur le bouton run. Entrer de nouveau les données. Lorsque l'exécution s'interrompt, le fichier contenant le point d'arrêt correspondant s'affiche dans la fenêtre source et une flèche horizontale indique la ligne courante (le programme s'arrête juste avant cette ligne).La commande:
Relancer le programme en cliquant sur run et re-entrer les données. Le programme s'arrêtera à la même ligne que précédemment. Continuer l'exécution en utilisant cette fois la commande step. Que constate-t'on ?
Rajouter un point d'arrêt au debut de la fonction Trier et juste avant la deuxième boucle for de cette même fonction. Relancer l'exécution et faire de même que pécédemment mais en utilisant cette fois la commande cont.
Conclusions ?
info breakpointsou plus simplement:
info b
clear numéro-de-ligneà l'aide du bouton clear (apres avoir sélectionné cette ligne à la souris) ou en tapant directement la commande.
break nom-du-fichier.c:nom-de-la-fonction(ne pas oublier le ".c" et le ":")
Lorsque le programme est arrêté dans une fonction, on peut visualiser ses variables au moyen de la commande ou du bouton print.
On peut soit taper en toutes lettres :
print nom-de-la-variableou bien cliquer sur le bouton print après avoir sélectionné la variable avec la souris dans la fenêtre contenant le texte source.
De manière plus générale, on peut afficher la valeur de
n'importe quelle expression valide en C
Exemple :
Dans la fonction Trier, afficher la valeur de:
swap, items[1], i + j, items[i].nom, items[i].age, etc...
Attention : ces expressions n'ont de sens que si elles sont définies (par exemple la variable i n'est correctement initialisée qu'après la première boucle for).
print* nom-de-la-variable
display expressionLe contenu de cette variable est alors affiché dans la fenêtre "de visualisation" . Cet affichage sera réactualisé jusqu'à ce que l'on fasse:
undisplay expression
La commande:
Exemple : On doit théoriquement se trouver dans la fonction Trier. Si ce n'est pas le cas, relancer l'exécution jusqu'a cette fonction. Cliquer sur le bouton where pour afficher la pile, puis utiliser les commandes up et down pour se déplacer dans la pile. Afficher les variables de la fonction Trier, puis celles de la fonction Choix, et enfin celles de la fonction main.
De même que les points d'arrêts, les interruptions arrêtent le déroulement du programme. Dans le cas qui nous interesse, celles-ci sont principalement de deux types :
Exemple : Relancer le programme et faire ^C au moment où le programme demande le premier nom. Afficher où l'on se trouve dans la pile à l'aide de la commande where ou du bouton stack.
Remarque: la commande cont permet alors de poursuivre l'exécution normalement.
Faire :
help nom-de-commandepour obtenir de l'aide sur cette commande.
De nombreuses commandes peuvent être abrégées. Par exemple:
r pour run b pour break s pour step n pour next c pour cont p pour print etc ....De plus, "retour-chariot" (sans rien taper d'autre) réexécute la dernière commande entrée.
On peut recompiler le programme sans sortir de gdb en tapant directement sous gdb la commande:
make(make est une commande propre à gdb qui active la commande make habituelle d'Unix).
Les commandes :
print expression call fonction(arguments)
permettent d'appeler interactivement les fonctions contenues dans le programme ainsi que la plupart des fonctions C des bibliothèques standard (comme par exemple "printf" etc...). Ceci peut-être très utile pour tester rapidement le comportement d'une fonction dans la mesure où l'on peut changer interactivement les arguments passés à cette fonction sans avoir à recompiler (surtout si l'on rajoute des points d'arrets dans cette fonction avant de l'appeler)
Exemple: Relancer le programme en tapant la commande :
call main()
Pour plus d'informations faire : help commande
Le but de l'exercice est de compléter le programme tri.
Compléter le programme afin de permettre un tri alphabétique ou décroissant. (plusieurs solutions possibles) Comment faire pour n'avoir à définir qu'une seule fonction de tri ? (on pourra par exemple s'inspirer de la technique utilisée par la fonction standard qsort() en regardant le manuel interactif de cette fonction).
Généraliser le programme pour un nombre quelconque d'items : utiliser des pointeurs et les fonctions malloc(), realloc() et free().
Permettre de sauvergarder les données et de les relire dans un fichier.