TP Debugger Gdb

Eric Lecolinet - Dept. INFRES - ENST
home page elc page cours dept. infres enst


Sommaire

  1. Introduction
  2. Préliminaires
  3. Compilation des programmes
  4. Lancement de xxgdb
  5. Utilisation de xxgdb
  6. Lancer l'exécution
  7. Points d'arrêt
  8. Contrôle de l'exécution
  9. Compléments sur les points d'arrêt
  10. Visualisation des variables
  11. Visualiser (et se déplacer dans) la pile
  12. Interruptions
  13. Compléments
  14. Aide en ligne
  15. Abréviations
  16. Recompilation
  17. Appel de gdb depuis emacs
  18. Appel de fonctions
  19. Autres commandes utiles
  20. Exercice
  21. Tri décroissant et alphabétique
  22. Vérification des entrées
  23. Mémoire dynamique
  24. Sauvegarde et relecture

1. Introduction

gdb est un debugger symbolique, c'est-à-dire un utilitaire Unix 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. C'est l'utilitaire que nous allons utiliser dans ce TP. L'interface mxgdb est également parfois disponible SGDG.

D'autres debuggers sont également disponibles à l'Ecole, suivant les salles et les machines. Leur syntaxe est légèrement différente, mais le principe général reste le même. Le plus courrant est dbx qui peut également être appelé via une interface graphique sous X-Window à l'aide des commandes debugger ou dbxtool (suivant la version du système d'exploitation).

Attention: le debugger n'est pas toujours independant du compilateur. Ainsi, seules les combinations suivantes sont toujours valides sur toutes les stations Sun :

Enfin, certains debuggers (et en particulier gdb) peuvent être directement appelé depuis les éditeurs de texte emacs et xemacs. Ceci permet de bénéficier d'un environnement de développement intégré (plus ou moins) similaire à ce que l'on peut aujourd'hui trouver dans le "monde PC". Cette possibité sera expliquée à la fin du TP.

1.1 Préliminaires

Créer un nouveau répertoire "tp-gdb" (sous votre compte) et y copier les fichiers sources (sans oublier les ".h" et le "Makefile" !) qui se trouvent dans :
	~domeo/TP-gdb
Votre répertoire devra alors contenir :
Tous ces fichiers sont nécessaires pour compiler correctement le programme.

1.2 Compilation des programmes

Les programmes C doivent être compilés avec le compilateur gcc avec l'option -g pour pouvoir être débuggés par gdb.

Si l'on utilise un Makefile (comme c'est le cas ici), il faut que la variable CFLAGS contienne l'option -g.
Ainsi la ligne :

	CFLAGS   =  -g
du Makefile indique que les fichiers C seront compilées avec l'option -g afin de pouvoir être débuggés.

D'autre part, la ligne:

	.KEEP_STATE:
placée en début de Makefile provoque à chaque appel de la commande make :

Compiler les fichiers et créer l'exécutable en tapant la commande : make

1.3. Lancement de xxgdb

pour lancer le débugger, tapez :

	xxgdb  nom-du-programme-à-debugger

dans une fenêtre shell (par exemple une fenêtre "xterm").

Après quelques secondes nécessaires à l'initialisation et à la lecture des fichiers à débugger, gdb entre en mode commande et attend les instructions de l'utilisateur.

On doit alors voir 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:

2. Utilisation de xxgdb

2.1. Lancer l'exécution

Pour lancer l'exécution du programme taper:
	run  arguments-du-programme
ou 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.

Exemple:

Après avoir compilé le programme tri, lancer xxgdb et exécuter le programme. Entrer les données demandées (2 ou 3 noms suffisent) et terminer la saisie en entrant un point suivi d'un "retour-chariot". Attention: le programme n'est pas complet (ce sera a vous de le compléter), seule la première option de tri (par age croissant) est implémentée.

2.2. Points d'arrêt

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).

2.3. Contrôle de l'exécution

La commande:

La différence entre step et next est que step permet d'"entrer" dans les fonctions pour les exécuter pas à pas alors que next les exécute sans s'arrêter.

Exemple:

Le programme étant toujours arrété dans la fonction Choix, continuer l'exécution pas pas au moyen de la commande next (ne pas oublier d'entrer une valeur quand vous arriverez au "scanf").

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 ?

2.4. Compléments sur les points d'arrêt

Pour afficher la liste des points d'arrêt faire:
      info  breakpoints
ou plus simplement:
      info  b

Pour effacer un point d'arrêt faire:

      clear  numéro-de-ligne
à l'aide du bouton clear (apres avoir sélectionné cette ligne à la souris) ou en tapant directement la commande.

Pour mettre un point d'arrêt dans une fonction qui est dans un autre fichier que celui qui est affiché l'écran:

Exemple:

Mettre un point d'arrêt dans les fonctions Lire et Afficher.

2.5. Visualisation des variables

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-variable
ou bien cliquer sur le bouton print après avoir sélectionné la variable avec la souris dans la fenêtre contenant le texte source.

Exemple:

Relancer le programme avec les mêmes points d'arrêt que précédemment et afficher le contenu des variables à chaque point d'arrêt.

De manière plus générale, on peut afficher la valeur de n'importe quelle expression valide en C

Exemples:

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).

Compléments:

Pour afficher la valeur pointée par un pointeur faire :

      print*  nom-de-la-variable
Pour afficher de manière permanente le contenu d'une variable ou d'une expression, faire:
      display  expression
Le 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

Enfin, le bouton locals permet d'afficher toutes les variables locales d'une fonction et le bouton args, ses arguments.

2.6. Visualiser (et se déplacer dans) la pile

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.

3. Interruptions

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 :

Dans les deux cas, il est possible de voir où le programme s'est arrêté et de visualiser l'état de ses variables. Ce qui est évidemment très pratique pour trouver les "bugs".

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.

4. Divers

Aide en ligne

Faire :
	help  nom-de-commande
pour obtenir de l'aide sur cette commande.

Abréviations

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.

Recompilation

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).

Appel de gdb depuis emacs ou xemacs

Il est possible d'appeler gdb depuis l'éditeur de texte emacs en tapant sous emacs la commande suivante:
	ESC-X gdb
xemacs possède également un bouton qui permet de lancer direcment gdb.

Noter que l'On peut également lancer la compilation depuis emacs au moyen de la commande :

	ESC-X compile

Appel interactif des fonctions

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()

Autres commandes utiles

Pour plus d'informations faire : help commande

5. Exercice

Le but de l'exercice est de compléter le programme tri.

5.1. Tri décroissant et alphabétique

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).

5.2. Vérification des entrées

5.3. Mémoire dynamique

Généraliser le programme pour un nombre quelconque d'items : utiliser des pointeurs et les fonctions `malloc' et `realloc'.

5.4. Sauvegarde et relecture

permettre de sauvergarder les données et de les relire dans un fichier.


home page elc page cours dept. infres enst

Page maintenue par Eric Lecolinet / ENST / INFRES.