Par Peter Meyer
Le débogage est le nom donné au processus de suppression des bugs dans les programmes informatiques. Cela ne peut jamais être complètement terminé, car "il y a toujours un dernier bug". Cependant, il est possible d'enlever tous les bugs sauf celui-là. Pour cela, l'utilisation d'un débogueur peut être très utile. Il s'agit d'un programme conçu pour vous permettre de passer en revue les instructions d'un autre programme étape par étape et d'examiner l'état de ce programme à chaque étape.
Le débogage commence dès que vous vous demandez pourquoi votre programme ne produit pas les résultats que vous souhaitez. La première chose à faire est de s'assurer que votre code C/C++ compile et se lie sans erreurs. Si un message d'erreur apparaît, votre code doit être modifié afin qu'il ne provoque plus cette erreur.
La deuxième chose à faire est d'examiner votre code et de comparer les résultats attendus avec ceux que vous obtenez réellement. Cependant, il arrive parfois qu'une inspection approfondie du code ne révèle aucun bug. Dans ce cas, vous pouvez souhaiter insérer du code de débogage. Ce code peut consister en des instructions assert pour vous assurer que les variables ont les valeurs que vous attendez à certains points de votre programme (par exemple, assert(n > 0)). Si les assertions échouent, le programme s'arrête avec un message d'erreur.
Le code de débogage peut également inclure des instructions pour afficher (en utilisant printf ou cout) les valeurs de certaines variables à certains endroits de votre code, vous donnant ainsi des informations sur ce qui se passe lorsque le programme s'exécute. Si cela n'éclaire toujours pas le bug, il est alors temps de lancer le débogueur.
Cela s'applique aux versions 5 et 6 du compilateur Microsoft Visual C++. Le débogueur dans d'autres versions peut différer dans certains aspects.
Pour utiliser le débogueur dans l'environnement de programmation Visual C++, vous devez avoir compilé et lié votre programme en utilisant la configuration "Debug" (et non "Release"). La configuration est définie via les options de menu Build | Set Active Configuration. Cette configuration est la configuration par défaut, donc vous n'avez pas besoin de la définir à moins que vous n'ayez auparavant changé la configuration en "Release".
Généralement, il n'est pas utile de passer en revue les instructions du programme en commençant par la première instruction dans main(). Il est préférable de faire exécuter le programme jusqu'à ce qu'il atteigne la partie de votre code où vous pensez que le bug se trouve. Il y a deux façons d'indiquer au débogueur d'exécuter le programme jusqu'à ce point. Vous pouvez placer le curseur à cet endroit dans votre code et appuyer sur Ctrl-F10 (ou Build | Start Debug | Run to Cursor). Le programme sera exécuté par le débogueur et, si tout se passe bien, il s'arrêtera à l'endroit dans votre code que vous avez sélectionné, et les fenêtres du débogueur s'ouvriront. Bien sûr, il est possible que le programme se termine avant d'atteindre l'endroit prévu. Dans ce cas, choisissez un endroit plus tôt dans le programme.
La deuxième façon d'indiquer au débogueur d'exécuter le programme jusqu'à l'endroit de votre code que vous souhaitez inspecter est de définir un "point d'arrêt" là-bas. Pour définir un point d'arrêt, placez le curseur à l'endroit souhaité et appuyez sur F9 (ou utilisez Bouton droit de la souris | Insert/Remove Breakpoint). Si un point d'arrêt a été défini, vous pouvez le supprimer en plaçant le curseur à côté et en appuyant sur F9. (Les points d'arrêt peuvent également être désactivés en utilisant F9 ou Bouton droit de la souris | Disable Breakpoint.) Une fois que vous avez défini un point d'arrêt, appuyez sur F5 (ou Build | Start Debug | Go) pour que le débogueur exécute le programme et s'arrête au point d'arrêt, après quoi les fenêtres du débogueur s'ouvrent (s'ils ne sont pas déjà ouverts).
Les fenêtres en bas à gauche et en bas à droite contiennent des noms et des valeurs de variables. Celles dans la fenêtre de gauche incluent les variables locales à la fonction qui est en cours d'exécution. Celles dans la fenêtre de droite sont des variables spécifiées par l'utilisateur. Pour spécifier une variable, cliquez sur la partie gauche de la première ligne vide, puis tapez le nom de la variable. Après avoir appuyé sur Entrée, la valeur de cette variable (si elle a une valeur) sera affichée. Vous pouvez ensuite observer comment les variables affichées changent de valeur lors de la poursuite de l'exécution du programme.
Appuyer sur F1 affiche une aide contextuelle. Par exemple, elle nous explique la différence entre les variables "Auto" et "Locals" :
Pour voir la valeur d'une variable sans avoir à taper son nom, placez le curseur quelque part dans le nom de la variable et appuyez sur Shift-F9 (ou Debug | QuickWatch).
Vous pouvez continuer l'exécution du programme de plusieurs manières. La plus simple est d'appuyer sur F10 (ou Debug | Step Over) pour exécuter l'instruction suivante (indiquée par la petite flèche jaune dans la marge gauche de la fenêtre de code). Appuyer répétitivement sur F10 parcourt successivement les instructions du programme. Prêtez attention aux informations données dans les fenêtres inférieures. Par exemple, si vous êtes à une instruction comme :
if ((j = atoi(buffer)) >= 2000)
(qui convertit la chaîne dans buffer en entier, place la valeur dans la variable j et la compare à 2000), après avoir appuyé sur F10, vous serez informé de la valeur retournée par atoi().
Si vous êtes à un appel de fonction, F10 fait exécuter cette fonction et, lorsque le débogueur reprend le contrôle, vous êtes à l'instruction suivante. À un appel de fonction, vous pouvez appuyer sur F11 (ou Debug | Step Into) pour entrer dans cette fonction (si le code de cette fonction a été compilé en mode "Debug"). Vous pouvez ensuite utiliser F10 pour parcourir les instructions dans cette fonction. Lorsque vous êtes à l'intérieur d'une fonction, vous pouvez appuyer sur Shift-F11 (ou Debug | Step Out) pour exécuter le reste de la fonction et revenir à l'instruction d'appel.
Lorsque le débogueur démarre, il ouvre une fenêtre pour la sortie du programme, de sorte que vous puissiez alterner entre le débogueur et cette fenêtre pour voir ce que le programme envoie à l'écran.
En plus de F10, F11 et Shift-F11, vous pouvez utiliser Ctrl-F10 (ou Debug | Run to Cursor) pour exécuter jusqu'à la position du curseur. Vous pouvez également définir d'autres points d'arrêt et utiliser F5 (ou Debug | Go) pour exécuter jusqu'à chacun d'eux tour à tour. Plusieurs points d'arrêt peuvent être actifs, et vous pouvez les désactiver ou les supprimer à volonté en plaçant le curseur dessus et en appuyant sur F9.
Si vous voulez voir la définition d'une variable, placez le curseur dans le nom de la variable et utilisez Bouton droit de la souris | Go to Definition. Il peut arriver que le débogueur vous dise qu'il ne peut pas le faire jusqu'à ce qu'il ait créé la base de données du navigateur, auquel cas demandez-lui de le faire.
Le navigateur est un outil utile qui vous permet d'obtenir la définition de toute variable dans votre programme et les emplacements dans votre programme où cette variable est utilisée ("références de variable"). Vous pouvez l'invoquer en utilisant Tools | Source Browser.
Si votre programme prend des arguments de ligne de commande, vous pouvez les définir lors du débogage en utilisant Project | Settings | Debug | Program arguments.
Pour redémarrer le programme depuis le début, appuyez sur Ctrl-Shift-F5 (ou Debug | Restart).
Pour arrêter le débogueur et revenir au mode édition, utilisez Shift-F5 (ou Debug | Stop Debugging).
| Touche | Description |
|---|---|
| F5 | Démarrer l'exécution du programme, exécuter jusqu'à un point d'arrêt. |
| Shift-F5 | Arrêter le débogage et revenir au mode édition du programme. |
| Ctrl-Shift-F5 | Redémarrer le programme en mode débogage. |
| F9 | Insérer, désactiver ou supprimer un point d'arrêt. |
| Shift-F9 | Obtenir la valeur d'une variable. |
| F10 | Exécuter l'instruction ou l'appel de fonction actuel. |
| Ctrl-F10 | Exécuter le programme jusqu'à la position du curseur. |
| F11 | Si l'instruction actuelle est un appel de fonction, entrer dans la fonction. |
| Shift-F11 | Si une fonction est en cours d'exécution, exécuter jusqu'à la fin et retourner à l'instruction appelante. |