Débogage pour grands débutants

Inévitablement, le code que nous écrivons en tant que développeurs de logiciels ne fait pas toujours ce à quoi nous nous attendions. Parfois, il fait quelque chose de complètement différent ! Lorsque l’inattendu se produit, la tâche suivante consiste à déterminer pourquoi, et bien que nous soyez tentés de simplement regarder notre code pendant des heures, il est plus facile et plus efficace d’utiliser un outil de débogage ou un débogueur.

Un débogueur, malheureusement, n’est pas quelque chose qui peut révéler magiquement tous les problèmes ou « bogues » dans notre code. Débogage signifie exécuter votre code pas à pas dans un outil de débogage tel que Visual Studio, pour trouver le point exact où vous avez commis une erreur de programmation. Vous comprenez ensuite quelles corrections vous devez apporter dans votre code et vos outils de débogage vous permettent souvent d’apporter des modifications temporaires afin de continuer à exécuter le programme.

L’utilisation efficace d’un débogueur est également une compétence qui prend du temps et de la pratique pour apprendre, mais qui est finalement une tâche fondamentale pour chaque développeur de logiciels. Dans cet article, nous présentons les principes fondamentaux du débogage et fournissons des conseils pour vous aider à démarrer.

Clarifier le problème en vous posant les bonnes questions

Il permet de clarifier le problème que vous avez rencontré avant d’essayer de le résoudre. Nous vous attendons à ce que vous ayez déjà rencontré un problème dans votre code, sinon vous n’êtes pas ici en essayant de déterminer comment le déboguer ! Avant de commencer le débogage, vérifiez que vous avez identifié le problème que vous essayez de résoudre :

  • Que s’attendiez-vous à ce que votre code fasse ?

  • Qu’est-ce qui s’est passé à la place ?

    Si vous rencontrez une erreur (exception) lors de l’exécution de votre application, cela peut être une bonne chose ! Une exception est un événement inattendu rencontré lors de l’exécution du code, généralement une erreur d’un certain type. Un outil de débogage peut vous amener à l’emplacement exact dans votre code où l’exception s’est produite et peut vous aider à examiner les correctifs possibles.

    Si quelque chose d’autre s’est produit, quel est le symptôme du problème ? Suspectez-vous déjà où ce problème s'est produit dans votre code ? Par exemple, si votre code affiche du texte, mais que le texte est incorrect, vous savez que vos données sont incorrectes ou que le code qui définit le texte d’affichage contient un certain type de bogue. En parcourant le code dans un débogueur, vous pouvez examiner chaque modification apportée à vos variables pour découvrir exactement quand et comment les valeurs incorrectes sont affectées.

Examiner vos hypothèses

Avant d’examiner un bogue ou une erreur, pensez aux hypothèses qui vous ont fait attendre un certain résultat. Les hypothèses cachées ou inconnues peuvent entraver l'identification d'un problème même lorsque vous examinez sa cause dans un débogueur. Vous pourriez avoir une longue liste d’hypothèses possibles ! Voici quelques questions à vous poser pour contester vos hypothèses.

  • Utilisez-vous l’API appropriée (c’est-à-dire l’objet, la fonction, la méthode ou la propriété appropriés) ? Une API que vous utilisez peut ne pas faire ce que vous pensez faire. (Après avoir examiné l’appel d’API dans le débogueur, la correction peut nécessiter un voyage vers la documentation pour vous aider à identifier l’API correcte.)

  • Utilisez-vous correctement une API ? Peut-être que vous avez utilisé l’API appropriée, mais que vous ne l’avez pas utilisée de la bonne façon.

  • Votre code contient-il des fautes de frappe ? Certaines fautes de frappe, comme une simple faute d’orthographe d’un nom de variable, peuvent être difficiles à voir, en particulier lorsque vous travaillez avec des langues qui ne nécessitent pas de variables à déclarer avant qu’elles ne soient utilisées.

  • Avez-vous apporté une modification à votre code et supposez qu’il n’est pas lié au problème que vous voyez ?

  • Vous attendiez-vous à ce qu’un objet ou une variable contienne une certaine valeur (ou un certain type de valeur) différente de ce qui s’est réellement passé ?

  • Connaissez-vous l’intention du code ? Il est souvent plus difficile de déboguer le code d’une autre personne. Si ce n’est pas votre code, il est possible que vous deviez passer du temps à apprendre exactement ce que fait le code avant de pouvoir le déboguer efficacement.

    Conseil

    Lorsque vous écrivez du code, commencez petit et commencez par du code qui fonctionne ! (Un bon exemple de code est utile ici.) Parfois, il est plus facile de corriger un jeu de code volumineux ou compliqué en commençant par un petit morceau de code qui illustre la tâche principale que vous essayez d’atteindre. Ensuite, vous pouvez modifier ou ajouter du code de manière incrémentielle, en testant à chaque point des erreurs.

En interrogeant vos hypothèses, vous pouvez réduire le temps nécessaire pour trouver un problème dans votre code. Vous pouvez également réduire le temps nécessaire pour résoudre un problème.

Parcourez votre code en mode débogage pour trouver où le problème s’est produit

Lorsque vous exécutez normalement une application, vous voyez des erreurs et des résultats incorrects uniquement après l’exécution du code. Un programme peut également se terminer de façon inattendue sans vous dire pourquoi.

Lorsque vous exécutez une application dans un débogueur, également appelé mode de débogage, le débogueur surveille activement tout ce qui se passe au fur et à mesure que le programme s’exécute. Il vous permet également de suspendre l’application à tout moment pour examiner son état, puis parcourir votre ligne de code par ligne pour observer chaque détail tel qu’il se produit.

Dans Visual Studio, vous entrez en mode débogage à l'aide de F5 (ou de la commande de menu Démarrer le débogage> ou du bouton Démarrer le débogageicône montrant le bouton Démarrer le débogage. dans la barre d’outils Débogage). Si des exceptions se produisent, l’Assistance à l’exception de Visual Studio vous amène au point exact où l’exception s’est produite et fournit d’autres informations utiles. Pour plus d’informations sur la gestion des exceptions dans votre code, consultez techniques et outils de débogage.

Si vous n’avez pas obtenu d’exception, vous avez probablement une bonne idée de l’endroit où rechercher le problème dans votre code. C’est à cette étape-là que l’on utilise des points d’arrêt avec le débogueur, pour pouvoir examiner le code plus attentivement. Les points d'arrêt constituent la fonctionnalité la plus élémentaire et essentielle pour un débogage fiable. Un point d’arrêt indique où Visual Studio doit suspendre votre code en cours d’exécution afin de pouvoir examiner les valeurs des variables, ou le comportement de la mémoire, la séquence dans laquelle le code s’exécute.

Dans Visual Studio, vous pouvez définir rapidement un point d’arrêt en cliquant sur la marge gauche en regard d’une ligne de code. Ou placez le curseur sur une ligne et appuyez sur F9 .

Pour vous aider à illustrer ces concepts, nous vous prenons dans un exemple de code qui contient déjà plusieurs bogues. Nous utilisons C#, mais les fonctionnalités de débogage s’appliquent à Visual Basic, C++, JavaScript, Python et d’autres langages pris en charge. L’exemple de code pour Visual Basic est également fourni, mais les captures d’écran sont en C#.

Créer un exemple d’application (avec certains bogues)

Ensuite, vous créez une application qui contient quelques bogues.

  1. Visual Studio et la charge de travail Développement .NET Desktop doivent être installés.

    Si vous n’avez pas encore installé Visual Studio, allez à la page des téléchargements de Visual Studio pour l’installer gratuitement.

    Si vous devez installer la charge de travail mais que Visual Studio est déjà installé, sélectionnez Tools>Obtenir des outils et des fonctionnalités. Le programme d’installation de Visual Studio démarre. Choisissez la charge de travail Développement .NET Desktop, puis choisissez Modifier.

  2. Ouvrez Visual Studio.

    Dans la fenêtre de démarrage, choisissez Créer un projet. Tapez console dans la zone de recherche, sélectionnez C# ou Visual Basic comme langue, puis choisissez application console pour .NET. Sélectionnez Suivant. Tapez ConsoleApp_FirstApp comme nom du projet, puis sélectionnez suivant.

    Si vous utilisez un autre nom de projet, vous devez modifier la valeur de l’espace de noms pour qu’elle corresponde au nom de votre projet lorsque vous copiez l’exemple de code.

    Choisissez le framework cible recommandé ou .NET 8, puis choisissez Créer.

    Si vous ne voyez pas le modèle de projet Application console pour .NET, accédez à Outils>Obtenir les outils et fonctionnalités, qui ouvre Visual Studio Installer. Choisissez la charge de travail Développement .NET Desktop, puis Modifier.

    Visual Studio crée le projet de console, qui apparaît dans Explorateur de solutions dans le volet droit.

  3. Dans Program.cs (ou Program.vb), remplacez tout le code par défaut par le code suivant. (Sélectionnez d’abord l’onglet de langue approprié, C# ou Visual Basic.)

    using System;
    using System.Collections.Generic;
    
    namespace ConsoleApp_FirstApp
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Welcome to Galaxy News!");
                IterateThroughList();
                Console.ReadKey();
            }
    
            private static void IterateThroughList()
            {
                var theGalaxies = new List<Galaxy>
            {
                new Galaxy() { Name="Tadpole", MegaLightYears=400, GalaxyType=new GType('S')},
                new Galaxy() { Name="Pinwheel", MegaLightYears=25, GalaxyType=new GType('S')},
                new Galaxy() { Name="Cartwheel", MegaLightYears=500, GalaxyType=new GType('L')},
                new Galaxy() { Name="Small Magellanic Cloud", MegaLightYears=.2, GalaxyType=new GType('I')},
                new Galaxy() { Name="Andromeda", MegaLightYears=3, GalaxyType=new GType('S')},
                new Galaxy() { Name="Maffei 1", MegaLightYears=11, GalaxyType=new GType('E')}
            };
    
                foreach (Galaxy theGalaxy in theGalaxies)
                {
                    Console.WriteLine(theGalaxy.Name + "  " + theGalaxy.MegaLightYears + ",  " + theGalaxy.GalaxyType);
                }
    
                // Expected Output:
                //  Tadpole  400,  Spiral
                //  Pinwheel  25,  Spiral
                //  Cartwheel, 500,  Lenticular
                //  Small Magellanic Cloud .2,  Irregular
                //  Andromeda  3,  Spiral
                //  Maffei 1,  11,  Elliptical
            }
        }
    
        public class Galaxy
        {
            public string Name { get; set; }
    
            public double MegaLightYears { get; set; }
            public object GalaxyType { get; set; }
    
        }
    
        public class GType
        {
            public GType(char type)
            {
                switch(type)
                {
                    case 'S':
                        MyGType = Type.Spiral;
                        break;
                    case 'E':
                        MyGType = Type.Elliptical;
                        break;
                    case 'l':
                        MyGType = Type.Irregular;
                        break;
                    case 'L':
                        MyGType = Type.Lenticular;
                        break;
                    default:
                        break;
                }
            }
            public object MyGType { get; set; }
            private enum Type { Spiral, Elliptical, Irregular, Lenticular}
        }
    }
    

    Notre intention pour ce code est d’afficher le nom de la galaxie, la distance à la galaxie, et la galaxie type tous dans une liste. Pour déboguer, il est important de comprendre l’intention du code. Voici le format d’une ligne de la liste que nous voulons afficher dans la sortie :

    nom de galaxie, distance, type de galaxie.

Exécuter l’application

Appuyez sur F5 ou sur le bouton Démarrer le débogageIcône montrant le bouton Démarrer le débogage. dans la barre d’outils Debug, située au-dessus de l’éditeur de code.

L’application démarre et aucune exception n’est signalée par le débogueur. Toutefois, la sortie que vous voyez dans la fenêtre de console n’est pas ce que vous attendez. Voici la sortie attendue :

Tadpole  400,  Spiral
Pinwheel  25,  Spiral
Cartwheel, 500,  Lenticular
Small Magellanic Cloud .2,  Irregular
Andromeda  3,  Spiral
Maffei 1,  Elliptical

Toutefois, vous voyez ce résultat plutôt :

Tadpole  400,  ConsoleApp_FirstApp.GType
Pinwheel  25,  ConsoleApp_FirstApp.GType
Cartwheel, 500,  ConsoleApp_FirstApp.GType
Small Magellanic Cloud .2,  ConsoleApp_FirstApp.GType
Andromeda  3,  ConsoleApp_FirstApp.GType
Maffei 1, 11,  ConsoleApp_FirstApp.GType

En examinant la sortie et notre code, nous savons que GType est le nom de la classe qui stocke le type de galaxie. Nous essayons de montrer le type de galaxie réel (comme « Spiral »), pas le nom de la classe !

Déboguer l’application

  1. L'application étant toujours en cours d'exécution, insérez un point d'arrêt.

    Dans la boucle foreach, cliquez avec le bouton droit à côté de la méthode Console.WriteLine pour ouvrir le menu contextuel et sélectionnez Point d’arrêt>Insérer un point d’arrêt dans le menu déroulant.

    foreach (Galaxy theGalaxy in theGalaxies)
    {
        Console.WriteLine(theGalaxy.Name + "  " + theGalaxy.MegaLightYears + ",  " + theGalaxy.GalaxyType);
    }
    

    Lorsque vous définissez le point d’arrêt, un point rouge apparaît dans la marge gauche.

    Comme vous voyez un problème dans la sortie, vous commencez à déboguer en examinant le code précédent qui définit la sortie dans le débogueur.

  2. Sélectionnez le bouton RedémarrerIcône montrant le bouton RestartApp dans la barre d’outils Débogage. dans la barre d’outils Déboguer (Ctrl + Maj + F5).

    L’application s’interrompt au point d’arrêt que vous définissez. La mise en surbrillance jaune indique où le débogueur est suspendu (la ligne jaune du code n’a pas encore été exécutée).

  3. Placez le curseur sur la variable GalaxyType à droite puis, à gauche de l’icône de clé, développez theGalaxy.GalaxyType. Vous voyez que GalaxyType contient une propriété MyGTypeet que la valeur de la propriété est définie sur Spiral.

    Capture d’écran du débogueur Visual Studio avec une ligne de code en jaune et un menu ouvert sous la propriété GalaxyType.

    « Spiral » est la valeur correcte que vous attendiez dans la console ! C'est donc un bon début que vous puissiez accéder à la valeur dans ce code lors de l'exécution de l'application. Dans ce scénario, nous utilisons l’API incorrecte. Voyons si vous pouvez résoudre ce problème lors de l’exécution du code dans le débogueur.

  4. Dans le même code, tout en déboguant, placez votre curseur à la fin de theGalaxy.GalaxyType et remplacez-le par theGalaxy.GalaxyType.MyGType. Bien que vous puissiez effectuer la modification, l'éditeur de code vous affiche une erreur (soulignée en rouge). (En Visual Basic, l’erreur n’est pas affichée et cette section de code fonctionne.)

  5. Appuyez sur F11 (Déboguer>Pas à pas détaillé ou le bouton Pas à pas détaillé dans la barre d’outils de débogage) pour exécuter la ligne de code actuelle.

    F11 fait avancer le débogueur (et exécute le code) une instruction à la fois. F10 (Pas à pas) est une commande similaire, et toutes deux sont utiles pour apprendre à utiliser le débogueur.

    Lorsque vous essayez de faire avancer le débogueur, la boîte de dialogue Rechargement à chaud s’affiche, indiquant que les modifications ne peuvent pas être compilées.

    Capture d’écran du débogueur Visual Studio avec une ligne de code mise en surbrillance en rouge et une zone de message avec l’option Modifier sélectionnée.

    La boîte de dialogue Modifier et continuer s’affiche, indiquant que les modifications ne peuvent pas être compilées.

    Capture d’écran du débogueur Visual Studio avec une ligne de code mise en surbrillance en rouge et une zone de message avec l’option Modifier sélectionnée.

    Remarque

    Pour déboguer l’exemple de code Visual Basic, ignorez les étapes suivantes jusqu'à ce qu'on vous demande de cliquer sur le bouton RedémarrerIcône montrant le bouton Redémarrer l’application dans la barre d’outils Déboguer..

  6. Sélectionnez Modifier dans la zone de message Rechargement à Chaud ou Modifier et Continuer. Un message d’erreur s’affiche maintenant dans la fenêtre Liste d’erreurs. L’erreur indique que le 'object' ne contient pas de définition pour MyGType.

    Capture d’écran du débogueur Visual Studio avec une ligne de code mise en surbrillance en rouge et une fenêtre liste d’erreurs avec deux erreurs répertoriées.

    Même si nous définissons chaque galaxie avec un objet de type GType (qui a la propriété MyGType), le débogueur ne reconnaît pas l’objet theGalaxy comme un objet de type GType. Que se passe-t-il? Vous souhaitez examiner n’importe quel code qui définit le type de galaxie. Lorsque vous faites cela, vous voyez que la classe GType a certainement une propriété de MyGType, mais quelque chose n’est pas correct. Le message d’erreur sur object s’avère être l’indice ; pour l’interpréteur de langage, le type semble être un objet de type object au lieu d’un objet de type GType.

  7. En examinant votre code lié à la définition du type de galaxie, vous trouvez la propriété GalaxyType de la classe Galaxy est spécifiée comme object au lieu de GType.

    public object GalaxyType { get; set; }
    
  8. Modifiez le code précédent comme suit :

    public GType GalaxyType { get; set; }
    
  9. Sélectionnez le bouton RedémarrerIcône montrant le bouton Redémarrer l’application dans la barre d’outils Déboguer. dans la barre d’outils Déboguer (Ctrl + Maj + F5) pour recompiler le code et redémarrer.

    À présent, lorsque le débogueur s’interrompt sur Console.WriteLine, vous pouvez pointer sur theGalaxy.GalaxyType.MyGTypeet voir que la valeur est correctement définie.

  10. Supprimez le point d’arrêt en cliquant sur le cercle de point d’arrêt dans la marge gauche (ou cliquez avec le bouton droit et choisissez point d’arrêt>Supprimer le point d’arrêt), puis appuyez sur F5 pour continuer.

    L’application s’exécute et affiche la sortie. Ça a l'air bien, mais tu remarques une chose. Vous attendiez que la petite galaxie Magellanic Cloud s’affiche sous la forme d’une galaxie irrégulière dans la sortie de la console, mais elle n’affiche aucun type de galaxie du tout.

    Tadpole  400,  Spiral
    Pinwheel  25,  Spiral
    Cartwheel, 500,  Lenticular
    Small Magellanic Cloud .2,
    Andromeda  3,  Spiral
    Maffei 1,  Elliptical
    
  11. Définissez un point d’arrêt sur cette ligne de code avant l’instruction switch (avant l’instruction Select en Visual Basic).

    public GType(char type)
    

    Ce code est l’endroit où le type de galaxie est défini, donc nous voulons examiner de plus près.

  12. Sélectionnez le bouton RedémarrerIcône montrant le bouton Redémarrer l’application dans la barre d’outils Déboguer. dans la barre d’outils Déboguer (Ctrl + Maj + F5) pour redémarrer.

    Le débogueur s’interrompt sur la ligne de code où vous définissez le point d’arrêt.

  13. Placez le curseur sur la variable type. Vous voyez une valeur de S (suivant le code de caractère). Vous êtes intéressé par une valeur de I, comme vous savez qu’il s’agit d’un type de galaxie irrégulière.

  14. Appuyez F5 et pointez sur la variable type à nouveau. Répétez cette étape jusqu’à ce que vous voyiez une valeur de I dans la variable type.

    Capture d’écran du débogueur Visual Studio avec une ligne de code en jaune et une fenêtre avec la valeur de variable de type 73 I.

  15. Appuyez à présent sur F11 (Déboguer>Effectuer un pas à pas détaillé).

  16. Appuyez sur F11 jusqu’à ce que vous arrêtiez sur la ligne de code dans l’instruction switch pour obtenir la valeur « I » (instructionSelect pour Visual Basic). Ici, vous voyez un problème clair résultant d’une faute de frappe. Vous attendiez que le code passe à l’emplacement où il définit MyGType comme type de galaxie irrégulière, mais le débogueur ignore ce code complètement et s’interrompt complètement sur la section default de l’instruction switch (instructionElse en Visual Basic).

    Capture d’écran montrant l’erreur de faute de frappe.

    En examinant le code, vous voyez une faute de frappe dans l’instruction case 'l'. Cela devrait être case 'I'.

  17. Sélectionnez le code de case 'l' et remplacez-le par case 'I'.

  18. Supprimez votre point d’arrêt, puis sélectionnez le bouton Redémarrer pour redémarrer l’application.

    Les bogues sont maintenant corrigés et vous voyez le résultat attendu !

    Appuyez sur n’importe quelle touche pour terminer l’application.

Résumé

Lorsque vous rencontrez un problème, utilisez le débogueur et les commandes d’étape telles que F10 et F11 pour rechercher la région du code avec le problème.

Remarque

S’il est difficile d’identifier la région du code où le problème se produit, définissez un point d’arrêt dans le code qui s’exécute avant que le problème ne se produise, puis utilisez les commandes d’étape jusqu’à ce que vous voyiez le manifeste du problème. Vous pouvez également utiliser des points de trace pour enregistrer des messages dans la fenêtre Sortie. En examinant les messages enregistrés (et en notant quels messages n’ont pas encore été enregistrés !), vous pouvez souvent isoler la région du code avec le problème. Vous devrez peut-être répéter ce processus plusieurs fois pour le limiter.

Lorsque vous trouvez la région du code avec le problème, utilisez le débogueur pour examiner. Pour trouver la cause d’un problème, inspectez le code du problème lors de l’exécution de votre application dans le débogueur :

  • Inspecter les variables et vérifier si elles contiennent le type de valeurs qu’elles doivent contenir. Si vous trouvez une valeur incorrecte, découvrez où la valeur incorrecte a été définie (pour déterminer où la valeur a été définie, vous devrez peut-être redémarrer le débogueur, examiner la pile d’appels , ou les deux).

  • Vérifiez si votre application exécute le code attendu. (Par exemple, dans l’exemple d’application, nous nous attendions à ce que le code de l’instruction switch définisse le type de galaxie sur Irrégulier, mais l’application a ignoré le code en raison de la faute de frappe.)

Conseil

Vous utilisez un débogueur pour vous aider à trouver des bogues. Un outil de débogage est en mesure de trouver des bogues à votre place uniquement s’il connaît l’intention de votre code. Un outil ne peut connaître que l’intention de votre code si vous, le développeur, exprimez cette intention. Vous devez pour cela écrire des tests unitaires.

Étapes suivantes

Dans cet article, vous avez appris quelques concepts généraux de débogage. Ensuite, vous pouvez commencer à en savoir plus sur le débogueur.