\documentclass[a4paper,11pt]{article}
\textheight 23 cm 
\textwidth 15cm
\topmargin -1.5 cm
\begin{document}
\begin{center}
{\Large Mettre au point un programme}
\end{center}

Lorsqu'un programme ne fonctionne pas comme pr\'evu, on peut souvent
d\'etecter des erreurs en l'ex\'ecutant en pas-\`a-pas (une ligne
de code apr\`es l'autre) et en examinant l'\'evolution du contenu
des variables. L'application qui permet de faire cela s'appelle un
d\'eboggueur\footnote{Pour des erreurs d'allocation m\'emoire,
on utilisera plut\^ot un logiciel sp\'ecialis\'e comme {\tt
  valgrind}}. 
Plusieurs interfaces existent, on pr\'esente ici  
\verb|gdb| sous \verb|emacs| qui s'ex\'ecute dans
l'environnement d'\'edition du texte source, les commandes
ci-dessous s'exécutent aussi dans la console gdb d'autres
environnements. N.B.~: il faut utiliser \verb|lldb| sur MacOS.
\begin{enumerate}
\item Utilisez l'option \verb|-g| lorsque vous compilez.
Pour utiliser le menu Compile d'emacs, modifiez la premi\`ere ligne du texte source comme par exemple:\\
\verb|// -*- mode:C++; compile-command:"g++ -g -Wall essai.cc" -*-|
\item Compilez le programme, on suppose dans la suite que le programme
compil\'e s'appelle \verb|a.out| ce qui est le cas sous Linux,
remplacer par \verb|a.exe| sous Windows.
\item Dans \verb|emacs|, s\'electionnez Debugger (GDB) dans le menu Tools
(ou tapez sur la touche \verb|Echap|, vous devez voir
apparaitre \verb|ESC-| au bout de quelques secondes, puis selon
la version d'emacs tapez \verb|xgud-gdb| ou \verb|xgdb|
et la touche \verb|Entree|). Vous devez alors voir dans la ligne d'\'etat
en bas:\\
\verb|Run gdb (like this): gdb a.out|\\
Modifiez si n\'ecessaire puis tapez \verb|Entree|. Le deboggueur est activ\'e.
\item Pour visualiser \`a la fois le source du programme, le
d\'ebbugueur et les entr\'ees/sorties du programme, il faut couper la fen\^etre
en trois (faire deux fois menu File-$>$Split Window ou raccourci clavier Ctrl-X 2),
et dans l'une des parties de s\'electionner le source (menu Buffers
ou raccourci Ctrl-X o).
\item L'\'etape suivante consiste \`a mettre un {\em point d'arr\^et}\/ 
pr\`es de l'endroit o\`u vous suspectez qu'il y a une erreur (par exemple
au d\'ebut d'une fonction suspecte). Il y a deux
m\'ethodes, soit en donnant le nom de la routine, par exemple pour le
programme principal \verb|main|:\\
\verb|b main|\\
soit dans le code source, en cliquant \`a gauche de la ligne ou
en tapant \verb|Ctrl-X| puis \verb|Ctrl-A| puis \verb|Ctrl-B|
\`a la ligne souhait\'ee. 
On peut aussi taper \verb|b|
suivi par le num\'ero de ligne dans le fichier source 
(ou \verb|b nom_ficher:numero_ligne|). 
Vous pouvez mettre plusieurs points d'arr\^et.
\item Puis on lance l'ex\'ecution du programme en cliquant sur Go ou
en tapant \verb|r| (pour run). On peut passer des arguments au programme
après \verb|r|.
\item Le programme s'ex\'ecute normalement jusqu'\`a ce qu'il atteigne
le point d'arr\^et. On peut alors visualiser le contenu d'une variable
en utilisant l'instruction \verb|p| suivi du nom de variable (p pour print), par exemple:\\
\verb|p modulo| puis touche \verb|Entree|\\
imprime le contenu de la variable \verb|modulo| (si elle existe).
\item L'instruction \verb|n| (next) ex\'ecute la ligne courante.
Pour ex\'ecuter ensuite plusieurs lignes \`a la suite, on tape plusieurs
fois sur la touche Entree. On peut aussi indiquer un param\`etre
num\'erique \`a la commande \verb|n|.
\item L'instruction \verb|s| (step in) permet de rentrer \`a l'int\'erieur
d'une fonction si la ligne courante doit ex\'ecuter cette fonction (alors
que \verb|n| ex\'ecute cette fonction en un seul pas, sauf si cette
fonction contient un point d'arr\^et)
\item L'instruction \verb|u| (until) ex\'ecute le programme sans arr\^et
jusqu'\`a ce que la ligne de code source suivante soit atteinte (ou une
adresse donn\'e en param\`etre). C'est
particuli\`erement int\'eressant pour sauter au-del\`a d'une boucle.
\item L'instruction \verb|c| (continue) permet de continuer l'ex\'ecution
jusqu'au prochain point d'arr\^et. On peut aussi indiquer un param\`etre
pour ignorer le point d'arr\^et un certain nombre de fois.
\item \verb|kill| permet de stopper
le programme en cours, 
\item \verb|d| permet de d\'etruire un point d'arr\^et (on donne alors
son num\'ero) ou tous les points d'arr\^et. On peut aussi temporairement
d\'esactiver ou r\'eactiver un point d'arr\^et 
(commandes \verb|disable| et \verb|enable|)
\item \verb|f 0|, \verb|f 1|, etc. permet de visualiser la
fonction appelante \`a l'ordre demand\'e, l'ordre est calcul\'e 
depuis la fonction interrompue
(0 pour la fonction actuelle, 1 pour la 1\`ere appelante, etc.),
ainsi que les variables de cette fonction. Cette commande peut
d'ailleurs \^etre utilis\'ee en cas de Segmentation fault sans mettre
de point d'arr\^et au pr\'ealable.
\item Vous pouvez corriger une erreur dans la fen\^etre d'\'edition,
recompiler le programme et revenir dans la fen\^etre \verb|gdb|
(c'est le buffer nomm\'e \verb|*gud-a.out*|) puis reprenez
ce mode d'emploi \`a l'\'etape 5
(relancer l'ex\'ecution du programme en tapant \verb|r|, etc.).
\item Pour quitter le d\'eboggueur, tapez \verb|q| (quit)
ou fermez le buffer \verb|*gud-a.out*| 
(activez ce buffer et choisissez \verb|Close|
dans le menu \verb|Files|)
\end{enumerate}

Remarques: 
\begin{itemize}
\item Les variables de type structur\'e ou les classes
s'affichent comme des structures C, m\^eme si vous avez red\'efini
l'op\'erateur \verb|<<|. Pour afficher une variable de ce type,
il est judicieux de pr\'evoir une m\'ethode:\\
\verb|void dbgprint() const { cout << *this << endl; }|\\
On peut alors visualiser une variable \verb|x| du type consid\'er\'e
en tapant\\ 
\verb|print x.dbgprint()|\\
Pour automatiser tout cela,
cr\'eez un fichier nomm\'e \verb|.gdbinit| et contenant\\
\verb|echo Defining v as print command for class types\n|\\
\verb|define v|\\
\verb|print ($arg0).dbgprint()|\\
\verb|end|\\
Dans la session \verb|gdb|, tapez \verb|v x| pour visualiser le contenu
de la variable \verb|x|.
\item Parmi les autres possibilit\'es int\'eressantes de gdb, il y a la 
modification du contenu d'une variable en cours
d'ex\'ecution (commande \verb|print variable=valeur|)
On peut aussi interrompre
le programme seulement si une condition est v\'erifi\'ee
(\verb|break .. if ..|).
\item Pour plus d'informations, vous pouvez taper \verb|help| dans la fen\^etre
du debuggueur pour obtenir l'aide en ligne ou \`a tout moment dans
\verb|emacs|, en tapant \verb|Ctrl-H I|, puis
\verb|Ctrl-S gdb| puis clic de la souris avec le bouton du milieu sur
\verb|gdb|.
\end{itemize}
 
\end{document}
