PROFDINFO.COM

Votre enseignant d'informatique en ligne

Déboguons!

Le débogueur intégré à Visual Studio est un outil puissant qui vous sera très utile tout au long de votre carrière. Il permet de voir ce qui se passe dans notre programme, une étape à la fois, en examinant le contenu des variables pendant l'exécution. C'est idéal pour résoudre des bogues étranges qu'on n'arrive pas à s'expliquer en regardant simplement le résultat de l'exécution.

Les points d'arrêt

Un point d'arrêt (breakpoint) est une ligne dans le code où vous voulez arrêter l'exécution normale du programme pour commencer à déboguer. Vous ne pourrez rien déboguer si vous n'avez pas au moins placé un point d'arrêt. On place un point d'arrêt simplement en cliquant dans la marge de gauche de notre code.

Un point d'arrêt dans du code

Il est possible de placer autant de points d'arrêt que désiré. On peut évidemment les enlever si nécessaire, simplement en cliquant dessus.

Exécuter avec ou sans débogage

Normalement, nous utilisons par défaut l'exécution sans débogage (Ctrl-F5), puisque ce mode fait une pause une fois l'exécution terminée, ce qui nous permet de voir le contenu de la console avant qu'elle soit fermée.

Si on veut utiliser les points d'arrêt, il nous faudra toutefois utiliser "Démarrer le débogage" (F5), sinon ils seront ignorés. On peut donc laisser les points d'arrêt en place et choisir de les utiliser ou non.

Le pas à pas

L'idée de mettre un point d'arrêt est de pouvoir ensuite suivre l'exécution de votre programme un pas à la fois. Pour ce faire, on appuie sur F5 (démarrer le débogage) et le programme s'exécute normalement jusqu'à ce qu'il atteigne le premier point d'arrêt. Ensuite, l'exécution est suspendue, comme mise à pause. Votre code revient à l'avant-plan et une flèche jaune apparaît sur le point d'arrêt -- la ligne de code est également surlignée:

L'exécution suspendue sur un point d'arrêt

La flèche jaune indique la ligne qui sera la prochaine à être exécutée. L'exécution est donc suspendue juste avant l'exécution de la ligne où se trouve le point d'arrêt. Vous pouvez alors:

  • Passer votre pointeur de souris sur une variable pour voir son contenu dans une bulle -- on peut cliquer sur la punaise dans la bulle pour la fixer à cet endroit;
  • Appuyer sur F10 pour faire un pas principal, c'est-à-dire avancer d'un pas dans l'exécution du code, mais sans entrer dans le code des fonctions. Par exemple, lorsqu'on passe sur un cout ou sur un sqrt, on n'a pas besoin d'exécuter leur code interne un pas à la fois -- on veut simplement exécuter la fonction au complet d'un coup et continuer à partir de là. Ce sera généralement l'option qu'on utilisera;
  • Appuyer sur F11 pour faire un pas détaillé, c'est-à-dire avancer d'un pas dans l'exécution du code en entrant dans le code des procédures et fonctions appelées. Ce sera pratique lorsque l'on codera nos propres fonctions;
  • Appuyer sur Shift-F11 pour faire un pas sortant, c'est-à-dire terminer d'un seul coup l'exécution de la fonction dans laquelle on est entré (avec F11 précédemment), puis revenir au niveau supérieur (là où on se trouvait avant d'entrer dans la fonction). Pratique si on a appuyé sur F11 par erreur et qu'on ne sait plus trop où on est rendu, ou si on a vu ce qu'on voulait voir dans la fonction.
  • Appuyer sur F5 pour relancer l'exécution normalement. Elle sera de nouveau suspendue au prochain point d'arrêt rencontré, s'il y a lieu. S'il n'y a pas d'autre point d'arrêt subséquent, l'exécution continuera jusqu'à la fin du programme.
  • Appuyer sur Shift-F5 pour arrêter complètement l'exécution.
  • Déplacer la flèche jaune en la glissant (pour aller exécuter immédiatement une partie du code qui se trouve ailleurs, ou réexécuter une partie de code déjà exécutée précédemment -- il y a quand même des risques si on fait n'importe quoi).

Notez qu'il existe des icônes dans la barre de boutons qui permettent aussi de réaliser ces tâches:

Les espions

Plutôt que de devoir constamment passer sa souris sur une variable pour la voir changer, on peut utiliser la fenêtre d'espions pour qu'elle soit affichée pour nous en permanence. La fenêtre d'espions apparaît normalement en dessous de la fenêtre du code pendant qu'on est en débogage. Si ce n'est pas le cas, on peut la faire apparaître en faisant Déboguer -> Fenêtre -> Espions -> Espion 1 (notez qu'on peut en ouvrir 4 différentes, toutes équivalentes).

On ajoute un espion en:

  • sélectionnant du code et en le glissant dans la fenêtre d'espions;
  • écrivant quelque chose directement dans la fenêtre d'espions.

On peut y mettre:

  • une variable;
  • une expression arithmétique;
  • une expression relationnelle;
  • une expression logique;
  • un savoureux mélange de tout ça.

Notez que les expressions n'ont pas besoin d'être des expressions directement tirées du code. Les variables, par contre, doivent être visibles au point du code où on est rendu en ce moment (pensez à la portée des variables locales).

Lorsqu'une valeur vient de changer (au dernier pas), elle devient rouge. Lorsqu'elle est pareille à ce qu'elle était au pas précédent, elle est noire.

Les points d'arrêt conditionnels

En cliquant sur un point d'arrêt avec le bouton de droite, on peut choisir "Condition" et définir une condition pour que le point d'arrêt s'active. On peut aussi passer le pointeur de la souris par-dessus le point d'arrêt et cliquer sur la roue d'engrenage qui apparaît alors:

Tant que la condition n'est pas vraie, le point d'arrêt est ignoré. Idéal pour s'arrêter à un moment précis d'une boucle, vous le constaterez lorsque vous en ferez!

On peut placer dans la boîte n'importe quelle expression relationnelle, qui peut utiliser des variables visibles à cet endroit du code. À chaque passage au point d'arrêt, la condition sera évaluée. Si elle est fausse, le point sera ignoré et l'exécution continuera. Si elle est vraie, le point d'arrêt s'activera et l'exécution sera suspendue.

Optionnellement, on peut également inscrire uniquement le nom d'une variable dans la case de condition et choisir "En cas de modification" dans la liste déroulante. Le point d'arrêt s'activera si la variable donnée n'a pas la même valeur que lors du dernier passage au point d'arrêt. Il faut toutefois savoir que la première fois que la variable est modifiée sur cette ligne ne comptera pas et n'activera pas le point d'arrêt. Cette utilisation n'a donc de sens que dans un contexte de répétitive.

Il est aussi possible de choisir "Nombre d'accès" plutôt que "Expression conditionnelle" afin de faire en sorte que le point d'arrêt s'active après un certain nombre de passage sur cette ligne (encore une fois, c'est surtout utile dans une répétitive). On peut alors demander au point d'arrêt de s'activer lorsque le nombre d'accès est égal à une valeur donnée, plus grand ou égal à une valeur donnée, ou un multiple d'une valeur donnée (pour ces cas où le programme semble agir étrangement une fois sur 3...)

L'option "Filtre" permet d'activer le point d'arrêt lorsque le programme est exécutée sur un ordinateur précis, dans un processus précis ou dans un thread précis, une utilisation qui sera bien peu courante dans le cadre de votre formation.

Une fois créé, un point d'arrêt conditionnel a l'air de ça:

Point d'arrêt conditionnel

Les assertions

Une assertion est la vérification d'une condition essentielle à la bonne marche du programme, vérification qui ne sera faite que pendant la phase de développement et pas pendant l'utilisation régulière du programme terminé.

L'idée est de valider une certaine condition sans laquelle rien ne peut fonctionner et tout arrêter si jamais la condition est fausse. Mais attention! On ne doit pas utiliser les assertions pour valider les intrants fournis par l'usager, puisque les assertions seront ignorées lorsque le programme sera entièrement terminé. On validera plutôt l'état de variables internes, dont nous sommes seuls responsables du contenu, afin de nous aider à identifier les situations problématiques pendant que l'on débogue et qu'on teste notre programme.

Une assertion, en C++, s'écrit simplement comme ceci:

assert(condition);

La condition peut être une expression relative ou une expression logique, qui peut être réduite à true ou false, exactement comme la condition qu'on placerait dans un if. Par exemple:

assert(Compteur < 100);

Ou:

assert(Diviseur != 0);

Au moment où la ligne est exécutée, la condition est vérifiée. Si elle est fausse, le programme s'arrête immédiatement et affichera un message d'erreur correspondant à la condition:

Assertion failed: Diviseur != 0

N'oubliez pas d'inclure la bibliothèque assert.h si vous désirez utiliser les assertions:

#include <assert.h>

Le mode Debug et le mode Release

Depuis le début, nous compilons toujours en mode Debug, simplement parce que c'est l'option par défaut. Il y a des différences importantes entre les deux modes:

Debug:

  • Compilation intégrant des informations pour le débogage
  • Aucune optimisation de l'exécutable
  • Les assertions sont exécutées

Release:

  • Compilation n'intégrant aucune information de débogage
  • Exécutable optimisé et plus rapide
  • Les assertions sont ignorées

On utilise normalement le mode Release une fois que le débogage est entièrement terminé, que les tests sont satisfaisants et que l'on s'apprête à remettre le programme aux utilisateurs. Comme les assertions sont ignorées, on peut simplement les laisser là et compiler en mode Release comme si de rien n'était.

On change le mode simplement en utilisant la liste déroulable au centre de la barre d'outils:

Exercices formatifs

Prenez votre solution à votre exercice 2.5 du cours d'algorithmie.

  1. Placez un point d'arrêt sur la première ligne de l'entête (un commentaire). Que se passe-t-il lorsque vous lancez l'exécution avec F5?
  2. Placez un point d'arrêt sur une ligne vide. Que se passe-t-il alors lorsque vous lancez l'exécution avec F5?
  3. Placez un point d'arrêt sur la ligne d'inclusion de la bibliothèque iostream. Que se passe-t-il alors lorsque vous lancez l'exécution avec F5?
  4. Placez un point d'arrêt sur une déclaration de variable. Que se passe-t-il alors lorsque vous lancez l'exécution avec F5?
  5. Placez un point d'arrêt sur la première ligne de code de votre programme qui n'est pas une déclaration. Lancez l'exécution avec F5.
    1. Utilisez la fenêtre "Variables locales" pour vérifier le contenu initial de vos différentes variables au début du programme.
    2. Faites avancer l'exécution du programme pas à pas et constatez le changement de couleur des variables dans la fenêtre "Variables locales" à mesure que les valeurs changent.
    3. Exécutez en pas à pas votre programme au complet jusqu'à la fin et observez tout ce qui se pase.
  6. Placez un point d'arrêt conditionnel sur la ligne du if et faites en sorte que ce point d'arrêt soit actif uniquement lorsque la variable Moyenne est égale à 60. Lancez l'exécution avec F5 et testez des cas où la moyenne est différente de 60 et un cas où elle est égale à 60 pour vérifier votre point d'arrêt.
  7. Pendant une exécution pas à pas, lorsque vous êtes sur un cout, faites un pas à pas détaillé. Constatez ce qui se passe. Comment pouvez-vous revenir à votre code sans arrêter l'exécution du programme et tout recommencer?
  8. Assurez-vous de déclarer trois constantes pour stocker la pondération de chacun des examens (et utilisez ces constantes dans vos calculs dans le code -- normalement c'est ce que vous auriez dû faire d'emblée). Avant la lecture des intrants, ajoutez une ligne de code de type assertion qui vérifie que la somme des pondérations donne bien 1 (ou 100%).
    1. Testez votre programme tel qu'il est (avec CTRL-F5 pour ignorer vos points d'arrêt), afin de vérifier que tout se passe normalement (si tout est bien fait, vous ne devriez constater aucune différence).
    2. Modifiez vos pondérations de façon à ce que leur somme ne donne plus 100%. Exécutez le programme avec CTRL-F5 (pour ignorer vos points d'arrêt) et constatez ce qui se passe.
    3. Laissez vos pondérations erronées et compilez votre programme en mode release. Exécutez-le avec CTRL-F5 et constatez ce qui se passe.
    4. Quelle serait une autre bonne assertion à faire dans ce programme?