Qu'est-ce qu'un débogueur et comment peut-il m'aider à diagnostiquer les problèmes?

Aug 19 2014

Ceci est destiné à être une question à usage général pour aider les nouveaux programmeurs qui ont un problème avec un programme, mais ne savent pas comment utiliser un débogueur pour diagnostiquer la cause du problème.

Cette question couvre trois classes de questions plus spécifiques:

  • Lorsque j'exécute mon programme, il ne produit pas la sortie que j'attends pour l'entrée que je lui ai donnée.
  • Lorsque j'exécute mon programme, il plante et me donne une trace de pile. J'ai examiné la trace de pile , mais je ne connais toujours pas la cause du problème car la trace de pile ne me fournit pas suffisamment d'informations.
  • Lorsque j'exécute mon programme, il plante à cause d'un défaut de segmentation (SEGV).

Réponses

68 Raedwald Aug 19 2014 at 20:49

Un débogueur est un programme qui peut examiner l'état de votre programme pendant que votre programme est en cours d'exécution. Les moyens techniques qu'il utilise pour ce faire ne sont pas importants pour comprendre les bases de l'utilisation d'un débogueur. Vous pouvez utiliser un débogueur pour arrêter l'exécution de votre programme lorsqu'il atteint un endroit particulier dans votre code, puis examiner les valeurs des variables dans le programme. Vous pouvez utiliser un débogueur pour exécuter votre programme très lentement, une ligne de code à la fois (appelée pas à pas ), pendant que vous examinez les valeurs de ses variables.

L'utilisation d'un débogueur est une compétence de base attendue

Un débogueur est un outil très puissant pour aider à diagnostiquer les problèmes avec les programmes. Et les débogueurs sont disponibles pour tous les langages de programmation pratiques. Par conséquent, être capable d'utiliser un débogueur est considéré comme une compétence de base de tout programmeur professionnel ou passionné. Et utiliser un débogueur vous - même est considéré comme un travail de base que vous devez effectuer vous - même avant de demander de l'aide à d'autres. Comme ce site est destiné aux programmeurs professionnels et passionnés, et non à un site d'assistance ou de mentorat, si vous avez une question sur un problème avec un programme spécifique, mais que vous n'avez pas utilisé de débogueur, votre question est très susceptible d'être fermée et rejetée. Si vous persistez avec des questions comme celle-là, vous serez finalement empêché d'en publier davantage.

Comment un débogueur peut vous aider

En utilisant un débogueur, vous pouvez découvrir si une variable a la mauvaise valeur et où dans votre programme sa valeur est passée à la mauvaise valeur.

En utilisant pas à pas, vous pouvez également découvrir si le flux de contrôle est comme prévu. Par exemple, si une ifbranche s'exécute quand vous vous attendez à ce qu'elle le soit.

Remarques générales sur l'utilisation d'un débogueur

Les spécificités de l'utilisation d'un débogueur dépendent du débogueur et, dans une moindre mesure, du langage de programmation que vous utilisez.

  • Vous pouvez attacher un débogueur à un processus exécutant déjà votre programme. Vous pourriez le faire si votre programme est bloqué.

  • En pratique, il est souvent plus facile d'exécuter votre programme sous le contrôle d'un débogueur dès le début.

  • Vous indiquez votre programme doit s'arrêter en indiquant le fichier de code source et le numéro de ligne de la ligne à laquelle l'exécution doit s'arrêter, ou en indiquant le nom de la méthode / fonction à laquelle le programme doit s'arrêter (si vous voulez arrêter comme dès que l'exécution entre dans la méthode). Le moyen technique que le débogueur utilise pour provoquer l'arrêt de votre programme est appelé un point d'arrêt et ce processus est appelé définition d'un point d'arrêt .

  • La plupart des débogueurs modernes font partie d'un IDE et vous fournissent une interface utilisateur graphique pratique pour examiner le code source et les variables de votre programme, avec une interface pointer-cliquer pour définir des points d'arrêt, exécuter votre programme et le suivre pas à pas.

  • L'utilisation d'un débogueur peut être très difficile à moins que les fichiers exécutables ou bytecode de votre programme n'incluent des informations de symbole de débogage et des références croisées à votre code source. Vous devrez peut-être compiler (ou recompiler) votre programme légèrement différemment pour vous assurer que les informations sont présentes. Si le compilateur effectue des optimisations étendues, ces références croisées peuvent devenir déroutantes. Vous devrez peut-être donc recompiler votre programme avec les optimisations désactivées .

39 SlugFiller Apr 05 2015 at 19:15

Je tiens à ajouter qu'un débogueur n'est pas toujours la solution parfaite et ne devrait pas toujours être la solution incontournable pour le débogage. Voici quelques cas où un débogueur pourrait ne pas fonctionner pour vous:

  • La partie de votre programme qui échoue est vraiment volumineuse (mauvaise modularisation, peut-être?) Et vous ne savez pas exactement par où commencer à parcourir le code. Passer en revue tout cela peut prendre trop de temps.
  • Votre programme utilise beaucoup de rappels et d'autres méthodes de contrôle de flux non linéaires, ce qui rend le débogueur confus lorsque vous le parcourez.
  • Votre programme est multi-thread. Ou pire encore, votre problème est causé par une condition de course.
  • Le code qui contient le bogue s'exécute plusieurs fois avant qu'il ne se déclenche. Cela peut être particulièrement problématique dans les boucles principales, ou pire encore, dans les moteurs physiques, où le problème pourrait être numérique. Même la définition d'un point d'arrêt, dans ce cas, vous ferait simplement le frapper plusieurs fois, le bogue n'apparaissant pas.
  • Votre programme doit s'exécuter en temps réel. C'est un gros problème pour les programmes qui se connectent au réseau. Si vous configurez un point d'arrêt dans votre code réseau, l'autre extrémité n'attendra pas votre passage, il va simplement expirer. Les programmes qui dépendent de l'horloge système, par exemple les jeux avec frameskip, ne sont pas non plus mieux lotis.
  • Votre programme effectue une certaine forme d'actions destructrices, comme l'écriture dans des fichiers ou l'envoi d'e-mails, et vous souhaitez limiter le nombre de fois que vous devez l'exécuter.
  • Vous pouvez dire que votre bogue est causé par des valeurs incorrectes arrivant à la fonction X, mais vous ne savez pas d'où viennent ces valeurs. Avoir à parcourir le programme, encore et encore, en définissant des points d'arrêt de plus en plus loin en arrière, peut être un énorme problème. Surtout si la fonction X est appelée de nombreux endroits dans le programme.

Dans tous ces cas, soit l'arrêt brutal de votre programme peut entraîner une différence des résultats finaux, soit la recherche manuelle de la ligne sur laquelle le bogue est causé est trop compliqué. Cela peut également se produire si votre bogue est un comportement incorrect ou un crash. Par exemple, si la corruption de la mémoire provoque une panne, au moment où la panne se produit, elle est trop loin de l'endroit où la corruption de mémoire s'est produite pour la première fois et aucune information utile n'est laissée.

Alors quelles sont les alternatives?

Le plus simple est simplement la journalisation et les affirmations. Ajoutez des journaux à votre programme à différents moments et comparez ce que vous obtenez avec ce que vous attendez. Par exemple, voyez si la fonction où vous pensez qu'il y a un bogue est même appelée en premier lieu. Voyez si les variables au début d'une méthode sont ce que vous pensez qu'elles sont. Contrairement aux points d'arrêt, il est normal qu'il y ait de nombreuses lignes de journal dans lesquelles rien de spécial ne se produit. Vous pouvez simplement rechercher dans le journal par la suite. Une fois que vous avez atteint une ligne de journal différente de ce que vous attendez, ajoutez-en plus dans la même zone. Réduisez-le de plus en plus loin, jusqu'à ce qu'il soit suffisamment petit pour pouvoir enregistrer chaque ligne dans la zone de bug.

Les assertions peuvent être utilisées pour intercepter les valeurs incorrectes lorsqu'elles se produisent, plutôt que lorsqu'elles ont un effet visible pour l'utilisateur final. Plus vite vous attrapez une valeur incorrecte, plus vous vous rapprochez de la ligne qui l'a produite.

Refactor et test unitaire. Si votre programme est trop gros, il peut être intéressant de le tester une classe ou une fonction à la fois. Donnez-lui des entrées, regardez les sorties et voyez lesquelles ne sont pas celles que vous attendez. Être capable de réduire un bogue d'un programme entier à une seule fonction peut faire une énorme différence dans le temps de débogage.

En cas de fuites de mémoire ou de piétinement de la mémoire, utilisez des outils appropriés capables de les analyser et de les détecter au moment de l'exécution. Être capable de détecter où se produit la corruption réelle est la première étape. Après cela, vous pouvez utiliser les journaux pour revenir à l'endroit où des valeurs incorrectes ont été introduites.

N'oubliez pas que le débogage est un processus qui revient en arrière. Vous avez le résultat final - un bug - et trouvez la cause qui l'a précédé. Il s'agit de travailler en arrière et, malheureusement, les débogueurs ne font que progresser. C'est là qu'une bonne journalisation et une analyse post-mortem peuvent vous donner de bien meilleurs résultats.