Journal Un debugger est-il indispensable ?

Posté par  (site web personnel) . Licence CC By‑SA.
Étiquettes : aucune
15
11
mai
2013

Ben oui, je ne la trouve pas si débile cette question. Moi à vrai dire je ne sors le debugueur que quand j'ai un segfault un peu louche, pour avoir une backtrace sur tous les threads. Le reste du temps c'est du debuggage à l'ancienne , au printf. C'est simple, c'est robuste, ça marche sur toutes les plateformes, ça marche même quand gdb ou windbg pour une raison quelconque n'est pas foutu de retrouver les noms de symboles du binaire. Alors pourquoi utiliser un outil lourd , bloaté, et buggé ?

  • # Super workflow

    Posté par  (site web personnel) . Évalué à 10. Dernière modification le 11 mai 2013 à 23:52.

    Perdre son temps à mettre des traces partout dans le code, en espérant couvrir tous les cas possibles, c'est super-productif. Et quand la partie intéressante n'est pas couverte, on repart sur un cycle «ajout de traces», compilation et reproduction du problème.

    Je fais exactement le contraire: les printf, je les garde pour les cas désespérés, quand pour une raison mystérieuse le debug a échoué.

    edit: j'avais pas vu l'allusion au journal précédent

    • [^] # Re: Super workflow

      Posté par  . Évalué à 4.

      A noter que j'ai deja vu des NSLog ecrits a la truelle planter une appli qui n'avait aucun probleme par ailleurs.

      Linuxfr, le portail francais du logiciel libre et du neo nazisme.

    • [^] # Commentaire supprimé

      Posté par  . Évalué à 10.

      Ce commentaire a été supprimé par l’équipe de modération.

      • [^] # Re: Super workflow

        Posté par  (site web personnel) . Évalué à 2.

        Comment tu gères ta base de teste unitaire ? Avec un fonction test() dans chaque fichier ? Et une fonction pour l'appeler dans le binaire principal ? Un binaire spécial ? Un truc de build plus complexe pour recompiler chaque fichier avec un harnais ?

        "La première sécurité est la liberté"

        • [^] # Commentaire supprimé

          Posté par  . Évalué à 3. Dernière modification le 13 mai 2013 à 14:46.

          Ce commentaire a été supprimé par l’équipe de modération.

          • [^] # Re: Super workflow

            Posté par  (site web personnel) . Évalué à 1.

            donc, tout le src/* avec un seul test/toto.c et tout dans un main.

            Tu ne scripts pas, par exemple pour utiliser diff ? Parfois, j'ai la flemme de faire des tests complets, or un bon gros exemple, est un bon moyen de vérifier que rien n'a cassé avec le diff issue d'une référence généré précédemment.

            "La première sécurité est la liberté"

            • [^] # Commentaire supprimé

              Posté par  . Évalué à 2.

              Ce commentaire a été supprimé par l’équipe de modération.

              • [^] # Re: Super workflow

                Posté par  (site web personnel) . Évalué à 1.

                tu as donc une lib pour tester les fichiers ? Des gestions de regexp par exemple ?

                "La première sécurité est la liberté"

                • [^] # Commentaire supprimé

                  Posté par  . Évalué à 2.

                  Ce commentaire a été supprimé par l’équipe de modération.

                • [^] # Re: Super workflow

                  Posté par  . Évalué à 2.

                  Pas réellement fais de C depuis presque 10 ans, mais y'a pas un framework de test pour C qui s'est développé ? Voir dans un langage de plus haut niveau histoire de pouvoir coder rapidement et pas avoir des millions de lignes de tests.

                  On retrouve ca dans certains langages. Par exemple écrire les tests en Groovy pour tester du Java. Vu la facilité de faire des bindings C je serais étonné que personne n'ait poussé le truc.

                  • [^] # Re: Super workflow

                    Posté par  (site web personnel) . Évalué à 1.

                    En général, les frameworks de tests essaye de faire le café, résultat tu peux passer plus de temps à debuguer un test qu'à coder, donc l'intérêt diminue fortement.

                    "La première sécurité est la liberté"

                    • [^] # Re: Super workflow

                      Posté par  . Évalué à 2.

                      Si tu regardes le genre de code que tu écris dans les tests, c'est typiquement le genre de chose que tu veux pas écrire en C par ce que tu vas passer ton temps à réécrire des centaines de méthodes qui sont built-in ou qui demandent 3 lignes de glue dans beaucoup d'autre environnements.

                      De l'autre côté, effectivement plus tu rajoutes de couches plus c'est le bordel.

                      C'était tout le sens de ma question, savoir où en était le compromis actuellement et qu'elles étaient les pistes et techniques qui avaient été, ou sont, explorées.

                      • [^] # Re: Super workflow

                        Posté par  (site web personnel) . Évalué à 2.

                        Ma seul certitude, pour l'instant, c'est que coder avec des assert() est priceless, quand c'est possible (et léger), mais la manipulation de fichier est un peu trop complexe pour cela.

                        "La première sécurité est la liberté"

                        • [^] # Re: Super workflow

                          Posté par  . Évalué à 2.

                          Si tu codes avec des assert() ça plante au premier test qui échoue, non ?
                          (en C, s'entend)

                          • [^] # Re: Super workflow

                            Posté par  (site web personnel) . Évalué à 2.

                            Oui.

                            Cela permet d'éviter des tests multiple à travers toutes les api. Tu découpes ton code en vérif, puis ensuite, tu considères tes entrées comme valide. Ton filet de sécurité est ton assert(), qui ne coute rien dans un code de production.

                            Cela permet aussi de faire un paquet de test, sans avoir "d'oracle" qui produit les données attendus. Ce qui peut être très chiant, tellement chiant que beaucoup de personne génèrent les fichiers une fois, et les utilisent comme référence. Cela ne teste rien du tout. Cela ne peut servir que de test anti regression.

                            "La première sécurité est la liberté"

                            • [^] # Re: Super workflow

                              Posté par  . Évalué à 2.

                              Ce qui peut être très chiant, tellement chiant que beaucoup de personne génèrent les fichiers une fois, et les utilisent comme référence.

                              Je ne comprends pas de quel oracle tu parles. Pourquoi des fichiers ? Par ailleurs, si ça plante dès le premier test, c'est un peu chiant pour l'intégration continue, non ?

                              • [^] # Re: Super workflow

                                Posté par  . Évalué à 4.

                                Il veut dire que générer des entrées de tests réaliste et suffisamment exhaustive pour passer dans tous les chemins, peut selon les projets, ressembler à de la divination.

                                Par exemple, pour modéliser un réseau de gaz tu as pleins de paramètres (taille de tuyaux, matière, diamètre, vanne, aiguillage…), et si ça peut être marrant de tester des cas impossibles, avoir des entrée cohérentes est une autre paire de manche.

                                Il ne faut pas décorner les boeufs avant d'avoir semé le vent

                    • [^] # Re: Super workflow

                      Posté par  (site web personnel) . Évalué à 3.

                      Peso j'ai bien apprécié check, dont la sémantique est claire, et vraiment pas usine à gaz.

      • [^] # Re: Super workflow

        Posté par  . Évalué à 0.

        j'ai aussi des tests de perfs pour ce que je juge indispensable : certains bugs insidieux se manifestent dans des perfs dégradées

        En même temps avec tous les tests sur tous les appels c'est un peu normal d'avoir des perfs dégradé :sifflote:

        Il ne faut pas décorner les boeufs avant d'avoir semé le vent

        • [^] # Commentaire supprimé

          Posté par  . Évalué à 2.

          Ce commentaire a été supprimé par l’équipe de modération.

          • [^] # Re: Super workflow

            Posté par  . Évalué à 3.

            Je pensais plus à la paranoïa du code où une valeur est testé 50 fois pour voir si elle est nulle ou pas. Combien de fois je tombe sur des truc en java qui ressemble à

            if ( machin.getBidule() != null && !machin.getBidule().isEmpty() ) // et encore c'est mieux que size() 
            {
              String leopard = machin.getBidule().get(0);
              if( leopard != null && !leopard.isEmpty()) 
              {
                 ...
              }
            }
            
            

            Et c'est fait quasiment systématiquement; si parfois je peux comprendre qu'on fasse la différence entre null et chaine vide, le plus souvent, dans le code où je suis ça n'a aucun sens. Ces tests alourdissent le code, et ont même tendance à planquer l'origine d'un problème; et encore c'est un truc trivial. Le hic c'est que le code est tellement foolproof, que lorsque les données d'entrée sont moisies on ne sait pas à quel endroit c'est mal branlé. Ça plante pas mais ça ne donne pas de résultats.

            À noter que getBidule() est du genre

            public List<String> getBidule(){ if( bidule_ == null ) bidule_ = new ArrayList<String>() ; return bidule_;}
            
            

            Il ne faut pas décorner les boeufs avant d'avoir semé le vent

    • [^] # Re: Super workflow

      Posté par  . Évalué à 2.

      C'est plus une question de discipline, au fil du temps mettre une trace pour chaque branche de code avec les variables discriminantes, c'est possible et ca marche assez bien.

      De plus j'utilise cppcheck patché (ou tout autre outils d'analyse de code) pour suivre la discipline des dev.

      C'est en général possible de configurer d'éditeur de code pour ajouter ca tout seul.

      A l'usage les traces partout dans le code est plus efficace que les autres méthodes dans mon cas.

      Comme ca on ne fait que des cycles de reproduction de Problèmes :-)

      En fait (et ca doit etre la meme chose chez tout les gens serieux) on a plusieurs niveaux de traces et de log, les logs sont toujours disponible sur les systèmes en production, pas les traces.

      Le tout va dans des fichiers, est configurable a distance (filtres, ..etc ).
      En fait le debugger est utilisé pour les segfault (une fois tout les ans).

      Pour des petits projets pas mal de méthodes peuvent marcher, mais quand ca devient gros je ne connais pas de méthode qui est plus efficace que plusieurs niveaux de traces.

    • [^] # Re: Super workflow

      Posté par  (site web personnel) . Évalué à 3.

      Je fais exactement le contraire: les printf, je les garde pour les cas désespérés,
      quand pour une raison mystérieuse le debug a échoué.

      Moi, j'ai quand même remarqué que la plupart des bugs que j'ai eu avec des applis graphiques n'étaient pas reproductibles lorsque l'application était lancée avec gdb, une idée du pourquoi de ce phénomène ?

  • # Le code déjà deboggué n'en a pas besoin

    Posté par  . Évalué à -3.

    1/ Le code est connu comme stable [à la rigeur testing] : pas besoin normalement.
    2/ Un code simple : moins de 1000 lignes: pas trop besoin je pense.
    3/ Si vous écrivez bien vos codes : de temps en temps vous aurez besoin…
    4/ Pour le reste: je doute qu'on puisse s'en passer…

    Maintenant, on peut toujours avoir besoin de debogger/tracer pour optimiser…

    Personnellement, je pense que c'est utile ne serait-ce que pour savoir comment çà fonctionne.

    Le lien avec l'autre poste est pertinente: répondre à votre question permet simplement de rappeler que l'on peut obtenir des résultats avec des manière différentes.

    Notez que je n'ai même pas pris le cas où c'est un inconnu que débogue ce qui sous entend presque que le besoin de déboguer ne se pose pas… :-)

    • [^] # Re: Le code déjà deboggué n'en a pas besoin

      Posté par  . Évalué à 7.

      Pendant qu'on parle de bugs, il faudrait se pencher sur le fâcheux problème qui affecte kadalka : pour une raison inconnue ses notes de commentaires sont très basses. Ça sent le truc mal pensé, pas fini. Je ne parle du code.

      • [^] # Re: Le code déjà deboggué n'en a pas besoin

        Posté par  . Évalué à 7.

        Le debogger fait un segfault : c'est le fiston de Robertix.

      • [^] # Re: Le code déjà deboggué n'en a pas besoin

        Posté par  . Évalué à -8.

        Pendant qu'on parle de bugs, il faudrait se pencher sur le fâcheux problème qui affecte kadalka : pour une raison inconnue ses notes de commentaires sont très basses. Ça sent le truc mal pensé, pas fini. Je ne parle du code.

        Bof…
        Merci pour la vanne: fallait pas.
        Mais de toutes les façons je reconnais que la notation n'est pas la meilleure.

    • [^] # Re: Le code déjà deboggué n'en a pas besoin

      Posté par  . Évalué à 5. Dernière modification le 12 mai 2013 à 09:08.

      Moi qui pensais que les règles suivantes étaient absolues :

      1) Tout code informatique comporte au moins un bug.
      2) Lorsqu'un bug est corrigé, la règle 1) s'applique.

      Il semble que kadalka a un autre avis.

      Il est vrai que j'ai une très longue expérience de programmation et que cela m'a peut-être rendu pessimiste.

      • [^] # Re: Le code déjà deboggué n'en a pas besoin

        Posté par  . Évalué à -8.

        Tout code informatique comporte au moins un bug.

        Non.
        La majorité des codes informatiques oui mais pas tous.

        1/ Tout dépend de ce que vous entendez par bugs…
        a) ne compile pas [cas des codes à compiler]
        b) ne s'exécute pas.
        c) le compilateur n'est pas approprié
        d) le défaut matériel fait que même le code correctement écrit bug
        e) on parle de bug lorsqu'on devrait parler d'absence d'un feature que l'on veut et qui n'avait pas été prévu au début.

        2/ Pour le cas e) il m'est arrivé d'avoir un code qui fonctionne à merveille mais je voulais un truc en plus.
        Si votre code est du style print hello et que ce code fonctionne il est évident qu'il n'y a pas de bug.

        Je résume c'est souvent l'absence d'un feature qui fait que l'on parle de bug… lorsque le code est parfaitement maîtrisable.
        [moins de 1000 lignes, le langage est maîtrisé, la doc est à niveau, etc.]

        Il semble que kadalka ait un autre avis.

        Soit on parle de TOUS les cas de figures, ou presque, et c'est ce que je fais, soit on parle de cas particuliers comme le votre où probablement vous codez de longues pages par semaine…
        Dans le premier cas, j'écris du code qui peut boguer au début [c'est exceptionnel si çà ne bogue pas], mais puisque c'est court [de zero à 10 000 lignes] au bout d'un moment çà ne bogue plus.
        Dans le deuxième cas, si vous écrivez du code pour plusieurs milliers de lignes, cela me paraît impossible que çà ne bogue pas, même si vous utilisez un framework, et en particulier si c'est lié au matériel [device issue]. Si en plus plusieurs personnes sont dessus…

      • [^] # Re: Le code déjà deboggué n'en a pas besoin

        Posté par  . Évalué à -7.

        Et il faut aussi se poser la question si un warning est un bug en soi ou pas.
        [Le compilateur peut se tromper aussi…]
        Tout dépend de son niveau d'exigence.

  • # Debugger en langage interprété

    Posté par  . Évalué à 10.

    Je dirais pour ma part que le langage utilisé peut inciter ou non à utiliser un debugger.

    Sur un site en PHP par exemple, je debugge tout le temps à coups de var_dump() et echo(). Sur les quelques programmes que j'ai pu faire en Python, j'ai toujours plus ou moins réussi à remonter à la source de mes bugs soit via des print, soit en passant par la console interactive.

    J'ai surtout l'impression que l'utilisation des debuggers est plus courante dans des langages compilés comme C(++) ou Java.

  • # Ça dépend ...

    Posté par  . Évalué à 4.

    … de ce qui est disponible avec le langage et son environment de prédilection.

    Exemple, Javascript et Firebug ou Common Lisp et SLIME, ceux sont deux environments dans lesquels le debugging devient plaisant et du coup on a presque jamais recourt aux printf tous moches.

    À côté de ça, je ne sais même pas s'il est possible de débugger en PHP sans printf, et pour le C il parait que GDB est pas mal mais je le trouve un peu spartiate (pour inspecter la mémoire c'est pas tip top).

    • [^] # Re: Ça dépend ...

      Posté par  . Évalué à 4.

      … de ce qui est disponible avec le langage et son environment de prédilection.

      J’ai aussi tendance à n’utiliser un débogueur que s’il est pratique.

      Pour Python, l’IDE Eric contient un débogueur très facile d’utilisation.

      « Le fascisme c’est la gangrène, à Santiago comme à Paris. » — Renaud, Hexagone

    • [^] # Re: Ça dépend ...

      Posté par  . Évalué à 3.

      je ne sais même pas s'il est possible de débugger en PHP sans printf

      sisi, tu dois te tourner vers xdebug. C'est intégré dans eclipse, netbeans, phpstorm et bien d'autres amha.
      Après, est ce que c'est mieux. Je ne sais pas je ne m'en sert pas.

  • # l'un ou l'autre

    Posté par  . Évalué à 2.

    c'est pas pratique.

    le debugger, comme on l'entend, fourmille d'informations. il y à un trop, là où la trace manuelle est, non trop précise, mais trop limitée.
    Printfer la valeur fautive c'est déjà connaitre 50 % ou plus de la solution.

    J'aimes bien l'idée de l'ide novateur dont-j'ai-oublié-le-nom qui peut faire des débugs sur des chemins courts dans le programme et afficher la sortie en live.

    On peut aussi se dire que,
    si j'ai recours à un debugger pour mon programme, alors, soit je suis un de ces torvalds humain et je n'ai vraiment pas le choix.
    Soit la complexité de mon programme m'à dépassé depuis longtemps et je devrais y appliquer une autre méthode de dev. genre par les tests. Car en réduisant le chemin parcouru pour vérifier chaque fonction, on en réduit sa complexité, donc on s'évite peut être le debugger. Un simple stacking mental du problème peut se révéler alors bien plus productif / rapide / je-perds-pas-mon-temps-dans-la-résolution-problèmes-mais-dans-l'implémentation-de-solutions.

  • # Ou pas

    Posté par  . Évalué à 5.

    debuggage à l'ancienne , au printf. C'est simple, c'est robuste, ça marche sur toutes les plateformes

    Je disconvient respectueusement. Il existe des plateformes où il n'existe pas de printf ou d'équivalent facile à mettre en place.

    Tous les nombres premiers sont impairs, sauf un. Tous les nombres premiers sont impairs, sauf deux.

    • [^] # Re: Ou pas

      Posté par  . Évalué à 8.

      Il existe aussi des cas ou les débuggeurs n'existent pas ou n'ont pas d'équivalent faciles à mettre en place.

    • [^] # Re: Ou pas

      Posté par  . Évalué à 8.

      Sauf que bien souvent quand t'as des soucis de malloc/free en C, un printf peut faire en sorte que ton bug disparaisse ou se déclenche ailleurs vu qu'il alloue de la mémoire… Et alors bonne chance avec ce genre de bug furtif!

  • # Pas si on est un grand ponte apparemment.

    Posté par  . Évalué à 8. Dernière modification le 12 mai 2013 à 08:07.

    Il y a 2 ans, j’avais vu passer une discussion sur un livre dans lequel de grands développeurs (dont Guido van Rossum (Python), Bjarne Stroustrup (C++) ou encore James Gosling (Java)) disaient ne jamais utiliser de débogueur.

    Après, d’un point de vue personnel, j’utilise assez rarement le débogueur mais ça varie beaucoup selon le langage (et du programme sur lequel je bosse). J’ai plus tendance à sortir le débogueur en Java qu’en C par exemple.

    De manière générale, mon cerveau + crayon/papier reste mon débogueur le plus efficace à ce jour.
    Après, les print, le débogueur interactif, Valgrind, les outils d’analyses statiques & cie je les sors au cas par cas, selon la situation et le problème.

    Édit : ha, je viens de retrouver le lien vers la discussion.

    • [^] # Re: Pas si on est un grand ponte apparemment.

      Posté par  (site web personnel) . Évalué à 2.

      J'ai du mal à utiliser des debuggueur, mais c'est vrai que dans 99% des cas, la stacktrace (quand je fais du Python ou du Java) me suffisent largement.

      En revanche, quand je fais du C, j'ai dû ressortir gdb de temps en temps. Et toujours en C, je passe régulièrement un coup de valgrind pour vérifier qu'il n'y a rien de perdu.

      • [^] # Re: Pas si on est un grand ponte apparemment.

        Posté par  . Évalué à 3.

        Un bug, c'est pas qu'une exception non rattrapee, ca peut etre un paquet de truc ou le programme s'execute tres bien mais me donne juste pas le resultat attendu… A quoi va te servir la stack trace inexistante dans ce cas?

        Linuxfr, le portail francais du logiciel libre et du neo nazisme.

        • [^] # Re: Pas si on est un grand ponte apparemment.

          Posté par  . Évalué à -9.

          Ce type de bug insidieux est extrémement rare, et si tu rencontre ce genre de bug souvent alors tu doit par exemple utiliser la programmation par contrat.

          • [^] # Re: Pas si on est un grand ponte apparemment.

            Posté par  . Évalué à 4.

            Pourquoi est ce que ce genre de bug serait plus rare qu'une exception qui remonte ? Au contraire un exception qui remonte signale très souvent une erreur grossière.

            • [^] # Re: Pas si on est un grand ponte apparemment.

              Posté par  . Évalué à -1.

              Je ne rencontre que très rarement ce genre de bug, mais je ne fait de programmation concurrente et les bases de code sont plutôt petites.

              • [^] # Re: Pas si on est un grand ponte apparemment.

                Posté par  . Évalué à 4.

                Dans tout les cas ton affirmation est mauvaise. Ce que tu dis implique que si tu utilises la programmtion par contrat alors tu n'as plus de bug. Ca serait la nouvelle du siècle…

                Maintenant dès que ton code commence à faire quelque chose, des erreurs dans la logique métier, dans l'implémentation, dans la spécification des méthodes, des invariants, dans l'utilisation de code tierce, des corruptions, des erreurs provoquées par la compatibilité ca va arriver.

                Une exception qui remonte par contre en général c'est juste un travail de porc ou la fin du monde.

          • [^] # Re: Pas si on est un grand ponte apparemment.

            Posté par  . Évalué à 4.

            Ce qui est rare chez moi c'est les segfault et les exceptions non rattrapees, parce que ca c'est pas vraiment dur a eviter.
            Et je suis pas le seul visiblement, des bugs dans des softs en production, ca se trouve souvent et ces softs ne crashent que tres peu.

            Des erreurs off by one, oublier de remettre un compteur a zero, une typo qui par le plus grand des hasards compile, c'est un peu plus courant.

            Linuxfr, le portail francais du logiciel libre et du neo nazisme.

            • [^] # Re: Pas si on est un grand ponte apparemment.

              Posté par  . Évalué à 2.

              Tu n'es pas le seul non… Je préfère même des bugs qui lèvent des exceptions, au moins je sais tout de suite ce qui ce passe qu'un bug "utilisateur" où le programme est tout content mais le résultat bancal.
              Pas plus tard que le mois dernier, sur ma déclaration contrôlée (par une "association de gestion agréée", pas des amateurs non ?), j'ai réussi sans le faire exprès à modifier ma déclaration de l'année précédente ! Tout ça parce qu'ils n'avaient pas prévu qu'on consulte dans un onglet en même temps qu'on saisisse dans un autre. Un debugger dans ce cas ne servira pas à grand chose…

        • [^] # Re: Pas si on est un grand ponte apparemment.

          Posté par  (site web personnel) . Évalué à 3.

          Je suis d'accord avec toi.

          Simplement, en général, quand je code un algo un peu compliqué, je code par petits bouts, en exécutant les fonctions avec du print un peu partout pour voir si j'ai le résultat attendu à chaque étape.
          Au final, je n'ai pas l'impression de perdre tant de temps que ça…

  • # il y a le bon paresseux et le mauvais paresseux

    Posté par  . Évalué à 9.

    Un debugger n'est utile que si on sait s'en servir, ceux qui s'en passent le font souvent par mauvaise paresse, le bon paresseux étant capable d'investir du temps à l'apprentissage si ça peut lui permettre de moins bosser ensuite.

    Membre de l'april, et vous ? https://april.org/adherer -- Infini, l'internet libre et non commercial : https://infini.fr

    • [^] # Re: il y a le bon paresseux et le mauvais paresseux

      Posté par  . Évalué à 5.

      ceux qui s'en passent le font souvent par mauvaise paresse, le bon paresseux étant capable d'investir du temps à l'apprentissage si ça peut lui permettre de moins bosser ensuite.

      Exactement. Si tu sais te servir de ton IDE et de ton debuger, tu vas plus vite à mettre un point d'arret et inspecter les variables qu'à écrire ton printf avec toutes les infos utiles dedans… Et quand tu te rends compte qu'il manque un truc dans ton printf bha tu as pas à recommencer.

      • [^] # Re: il y a le bon paresseux et le mauvais paresseux

        Posté par  . Évalué à 1.

        Si t'as mis le mauvais point d'arrêt tu vas devoir recommencer aussi…

        Le print a d'autres avantages : celui de pouvoir exécuter ton programme en entier sans intervenir à chaque point d'arrêt, justement. Tu exécutes, et tu inspectes les traces après coup. Ça peut être largement plus commode que de devoir prendre la main à chaque fois qu'un point d'arrêt est atteint (surtout s'il est atteint souvent).

        • [^] # Re: il y a le bon paresseux et le mauvais paresseux

          Posté par  . Évalué à 3.

          Tu peux faire continuer automatiquement un débuggeur une fois arrivé à un point d'arrêt, en affichant au passage les informations que tu veux, ou continuer automatiquement sauf si une condition particulière est atteinte. Ça demande probablement un peu plus de travail qu'un printf inséré dans le code, mais d'un autre coté on peut afficher d'autres informations que celles disponible dans un simple printf.

          Tous les nombres premiers sont impairs, sauf un. Tous les nombres premiers sont impairs, sauf deux.

        • [^] # Re: il y a le bon paresseux et le mauvais paresseux

          Posté par  . Évalué à 5.

          Si t'as mis le mauvais point d'arrêt tu vas devoir recommencer aussi…

          Relancer le programme seulement, pas le recompiler comme avec des printf.

          Ça peut être largement plus commode que de devoir prendre la main à chaque fois qu'un point d'arrêt est atteint (surtout s'il est atteint souvent).

          La plupart des debuggers modernes permettent de placer des point d'arrêt conditionnels. On défini un test sur le contexte et le debugger ne s'arrête que s'il renvoie true.
          Le fait qu'on passe souvent à un endroit n'a plus d'importance. Le debugger ne s'arrêtera que dans le cas qu'on a fixé.

          • [^] # Re: il y a le bon paresseux et le mauvais paresseux

            Posté par  . Évalué à 4.

            Relancer le programme seulement, pas le recompiler comme avec des printf.

            Ça ne fait pas grande différence si ton langage ne nécessite pas de compilation manuelle :-)

            La plupart des debuggers modernes permettent de placer des point d'arrêt conditionnels. On défini un test sur le contexte et le debugger ne s'arrête que s'il renvoie true.

            Si tu dois commencer à programmer ton debugger, ce n'est pas plus rapide à mettre en place que des traces à base de print.

            • [^] # Re: il y a le bon paresseux et le mauvais paresseux

              Posté par  . Évalué à 3.

              Si tu dois commencer à programmer ton debugger, ce n'est pas plus rapide à mettre en place que des traces à base de print.

              Ça dépend des conditions, écrire list.size() < 42 par exemple ne prends pas beaucoup de temps et évite d'avoir 200 ligne de printf à analyser. Par contre, les printf, c'est pratique pour voir les valeurs avant que le bug se produise (plutôt que de devoir relancer le debug en espérant que le bug soit au même endroit.

              « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

    • [^] # Re: il y a le bon paresseux et le mauvais paresseux

      Posté par  . Évalué à 4.

      Pour moi un problème des debugger, c'est quand on est en remote c'est assez vori très compliqué et impossible quand on est en production. Donc tu met assez d'informations dans les logs pour pouvoir comprendre ce qui s'est passé et avec un peu de pot tu fais gaffe à tes effets de bords (que tu limite) et donc tu peut facilement afficher l'ensemble des données d'entrées et de sorties de tes algos.

      Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

      • [^] # Re: il y a le bon paresseux et le mauvais paresseux

        Posté par  . Évalué à 1.

        Pour moi un problème des debugger, c'est quand on est en remote c'est assez vori très compliqué et impossible quand on est en production.

        Aïe, mes yeux.

        • [^] # Re: il y a le bon paresseux et le mauvais paresseux

          Posté par  . Évalué à 9.

          Ben, tu as un bug qui n'arrive qu'en production, comment fais-tu pour le diagnostiquer ? Tu l'ignores parce que « chez moi ça marche » ?

          • [^] # Re: il y a le bon paresseux et le mauvais paresseux

            Posté par  (site web personnel) . Évalué à 1.

            Sinon y a les traces (qui sont déjà présentes dans le soft) dont on peut faire varier le niveau (error, warning, all…), ou alors sur lesquelles on peut mettre des filtres. Si c'est un cas qui n'est reproductible qu'en production, c'est déjà mieux que d'essayer de deviner au doigt mouillé.

        • [^] # Re: il y a le bon paresseux et le mauvais paresseux

          Posté par  . Évalué à 3.

          Je ne comprends pas très bien.

          Tu dis qu'il faut utiliser un debuger en prod ? Tu dis qu'il faut avoir résolu tous les bugs avant d'arriver en prod ? Si c'est ce dernier cas, tu es vraiment naïf pour imaginer qu'il n'y a pas de bug en prod (regarde la liste des bugs de wheezy par exemple ou de linux c'est plus petit peut être).

          Le debugger sert à déceler un d'où vient un bug. Il est tout à fait concevable de s'en servir sur un code qui est déjà releasé/livré, si un bug apparaît.

          Au contraire je trouve les debuggers moins utile en phase de développement « pure ».

          Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

          • [^] # Re: il y a le bon paresseux et le mauvais paresseux

            Posté par  . Évalué à 1.

            Je ne dis pas qu'aucun bug n'arrive jusqu'en prod mais qu'on ne debug pas direct sur la prod. La prod c'est un environnement contrôlé où on ne bricole pas avec ses gros doigts.
            S'il y a un bug, on le qualifie, on trouve un scénario de reproduction. On fait un fix, on le livre, il est testé et on installe la build qui a été validée. Bref on essaie de rester dans un cadre maîtrisé.
            Dans la plupart des cas, les développeurs n'ont pas accès à la prod et il est juste interdit de le leur donner. C'est en particulier le cas dès que des données sensibles y transitent.

            • [^] # Re: il y a le bon paresseux et le mauvais paresseux

              Posté par  . Évalué à 2.

              Je n'ai pas dis le contraire. Juste que pour le qualifier/trouver un scénario de reproduction, tu n'a rien d'autre que les logs que tu génère.

              Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

            • [^] # Re: il y a le bon paresseux et le mauvais paresseux

              Posté par  . Évalué à 4.

              Je ne dis pas qu'aucun bug n'arrive jusqu'en prod mais qu'on ne debug pas direct sur la prod. La prod c'est un environnement contrôlé où on ne bricole pas avec ses gros doigts.
              S'il y a un bug, on le qualifie, on trouve un scénario de reproduction. On fait un fix, on le livre, il est testé et on installe la build qui a été validée. Bref on essaie de rester dans un cadre maîtrisé.

              en théorie, oui.

              Après en fonction du type de bug, son impact, la pression de la hiérarchie, le temps nécessaire à synchroniser sur la test… il m'est déjà arrivé à debugger en prod. D'autant plus quand ça n'arrive que sur la prod.

      • [^] # Re: il y a le bon paresseux et le mauvais paresseux

        Posté par  . Évalué à 1.

        oui.. Mais bon d'un autre côté c'est pas terrible pour les IO si tu logs tout et n'importe quoi en permanence.
        J'ai un cas en tête où se serait dévastateur pour l'expérience utilisateur.

        Par contre en cas d'erreur fatale j'ai tendance à logger tout et n'importe quoi effectivement.

  • # Je tente les 2

    Posté par  . Évalué à 4.

    En général, pour comprendre un bug, j'aime bien saisir le problème dans sa globalité.

    J'active donc les traces de debugage et si le programme est parti en segfault, je tente une session gdb. L'idée est de me mettre rapidement en situation, car 9 fois sur 10 il y a un gros indice a portée de main, le tout est de le trouver rapidement.

    Si j'ai besoin d'inspecter plus pour cerner le problème, je vois selon:
    - s'il y a peu de variable en jeu, je rajoute une trace, c'est assez rapide
    - s'il y a beaucoup de variable et que c'est facile de mettre un breakpoint, je me lance dans une session gdb.

    Au final, je me passe de gdb dans la grande majorité des cas, notamment car je fais en sorte d'entretenir mes traces de debug afin qu'elles soient lisibles.

  • # strace

    Posté par  (site web personnel) . Évalué à 4.

    Tout d'abord comme on l'a dit précédemment, cela dépend en effet aussi du langage et de l'environnement (ex: firebug (pour firefox) ou webinspector (pour les webkits) pour faire du JavaScript).

    Mais pour les langages compilés, avant de sortir l'artillerie lourde, on peut aussi tenter un petit strace pour détecter le problème. Cela marche en plus même si on a pas les sources, même sur des binaires "strippé" ou même sans avoir à recompiler pour rajouter plus de symboles.

    Pour les script (shell) aussi, rajouter un petit "set -x" vers le début répond aussi souvent au besoin.

    Pour moi le débogueur peut-être très instructif pour mieux maîtriser son langage et son compilateur, mais une fois les deux bien maîtrisé, s'en servir signifie à mon avis surtout que l'on ne maîtrise pas son code.
    Sauf peut-être pour la minorité qui joue avec du hardware en betâ ou très ésotérique, dans quel cas un débogueur peut permettre d'identifier un bug hardware (instruction mal routé/"codé", zone mémoire flottante)… avant de sortir de l'artillerie encore plus lourde : les sondes.

    A noter enfin que bien maîtriser un débogueur nécessite aussi des connaissances sur l'architecture, zones mémoires, ordonnanceur, etc… que beaucoup de développeurs n'ont pas.

    Je moinsse, tu moinsses, il moinsse, nos bots moinssent ...

    • [^] # Re: strace

      Posté par  . Évalué à 3.

      s'en servir signifie à mon avis surtout que l'on ne maîtrise pas son code.

      Et si c'est le code de quelqu'un d'autre qu'on reprend ?

      • [^] # Re: strace

        Posté par  (site web personnel) . Évalué à 3.

        …qui lui-même l'avait repris de quelqu'un d'autre, qui avait comme consigne de juste corriger les bugs rapportés et pas de rationaliser le code (prends trop de temps, pas de budget pour les développeurs et les testeurs, trop de risques de régressions…). C'est comme ça qu'à la fin on se retrouve avec un plat de spaghettis, et que les coûts de maintenances se démultiplient (bizarre, à l'origine l'idée était de limiter les coûts).

        • [^] # Re: strace

          Posté par  . Évalué à 2.

          C'est quand même sympa dans le logiciel libre de reprendre le code que quelqu'un d'autre a écris, tu ne crois pas ? Réinventer la roue plutôt que d'utiliser celle que le voisin propose librement, je sais que c'est à la mode, mais mettre les efforts en commun ça me semble aussi une bonne idée.

          Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

    • [^] # Re: strace

      Posté par  (site web personnel, Mastodon) . Évalué à -1.

      Pour abonder dans ton sens, je n'ai pas rencontrer d'utilisateur d'Ada qui utilise un débogueur…
      Et en C, quand on n'est pas un novice ou qu'on ne joue pas sur du matos exotique, le débogueur ne sert que si on récupère un code exotique…
      Ceci dit, il n'est utile et efficace que si l'on sait s'en servir…

      “It is seldom that liberty of any kind is lost all at once.” ― David Hume

  • # logs d'utilisation

    Posté par  . Évalué à 1.

    Je n'utilise pratiquement jamais de debugger, par contre je génère toujours une tonne de logs sur l'utilisation. En python on a de très belles traces ça permet assez rapidement de voir où est le problème dans le code, par contre ce qui est plus dur c'est de savoir par quel cheminement l'utilisateur est arrivé jusque là !

  • # Développement piloté par le debugger

    Posté par  (site web personnel) . Évalué à 4.

    Tous les debugger ne sont pas lourd. Certains sont même au coeur du système et le rapport change. Je pense notamment à Smalltalk qui inscrit le debugger dans le processus de développement (ex: http://www.pharocasts.com/2010/08/see-how-to-get-data-from-url-parse-xml.html ), même en TDD (ex: http://www.pharocasts.com/2010/07/live-testing-with-autotest.html ).

    Du coup le debugger améliore la productivité et ne s'utilise pas seulement lorsque quelque chose va mal.

    Malheureusement la très grande majorité des environnements de développement ont un debugger lourd, limité parce que le langage rend difficile leur implémentation.

  • # Pas forcement un exemple !

    Posté par  (site web personnel) . Évalué à 2.

    Préambule, je ne code qu'en C++ ou presque et je suis exclusivement sur Linux.

    Déjà que je ne suis pas un fan d'ide dans le sens eclipse et j'avoue avoir également un peu de mal à me servir d'un debugger (gdb). Alors pour le moment, c'est juste du gvim, gedit…

    Pour le moment, je trouve que les / mes bug se trouvent le plus souvent quand je lance des batteries de tests unitaires et que le résultat retourné est incorrect. Alors du coup, je commente un peu mes fichiers de tests avec un //#define DEBUG_VERBOSE un peu moche que je commente / décommente au besoin… Je croise le tout avec un makefile un peu chiadé et pour le moment, ça me suffit…

    Mais bon, je suis un peu entrain de prendre conscience que ça ne me ferai pas de mal d'en apprendre un peu plus sur GDB et eclipse (pour par exemple le refactoring).

    La réalité, c'est ce qui continue d'exister quand on cesse d'y croire - Philip K. Dick

  • # Je debug pour apprendre le fonctionnement d'un logiciel C/C++ que je ne connais pas

    Posté par  . Évalué à 7.

    Je trouve que c'est un outil très efficace pour s'y retrouver rapidement dans une large base de code. Selon moi, les logiciels libres manquent de documentation, "diagrammes" quand au fonctionnement et interaction entre les élements du code, je ne suis pas un über codeur en C/C++.

  • # Oui

    Posté par  . Évalué à 5.

    parce que le printf debugging c'est mal, ça peut faire apparaitre des bugs étranges ou les faire disparaitre (dans tous les cas c'est la merde)

    parce que savoir quand une variable est modifié et par ou (avoir la stack), est parfois essentiel à la correction d'un bug.

    parce que des traces trop verbeuses peuvent avoir un gros impact sur les perfs; l'appli sur laquelle je bosse fait des traces de plusieurs centaines de Mo à l'heure, et on essaye de retreindre…

    Parce que changer une valeur sans avoir à tout recompiler permet de tester des cas plus larges.

    Parce que les tests unitaires ne valent jamais un utilisateur.

    Parce qu'un fichier core, est le bonheur du dev devant corriger un bug.

    Parce que dès qu'on joue un petit peu avec des theads, les traces ont un impacte dans l’ordonnancement.

    Parce que les debuggeur ont largement évolués depuis la grande époque où poser un breakpoint sur un symbole dans gdb te faisais passer pour un gourou, et que maintenant on peut avoir la complétion automatique ou la pose d'un breakpoint sur une regexp. Parce que les watchpoint c'est quand même vachement plus pratique que de devoir recompiler tout le code.

    Parce que quand on fait de l'objet, trouver la chaine pertinente à écrire dans les traces c'est pas toujours une partie de plaisir

    Parce que emacs avec gdb-multi-window ça fait quand même vachement plus gourou, que le gars qui rajoute à tout va std::cout << FILE << ":" << LINE << "chaine absurde car les traces sont trop verbeuse, ça permet de faire un grep" << std::endl ;

    Parce que gdb --pid $(pidof progEnCoursDexecution) permet de voir pourquoi le truc ne fait pas ce qu'il devrait sans avoir à recompiler et rajouter des traces.

    Parce qu'une fonction ne dépends pas que de ses paramètres (accès à une base de donnée par exemple), et que tout tracer est vraiment galère.

    Parce que ça ne plante jamais là où ça devrait.

    Parce que valgrind n'est pas toujours suffisant

    Bref, si j'use pas mal le printf debugging, bien souvent je m’aperçois que j'aurais été plus rapide avec un gdb

    Il ne faut pas décorner les boeufs avant d'avoir semé le vent

    • [^] # Re: Oui

      Posté par  (site web personnel) . Évalué à 3.

      parce que le printf debugging c'est mal, ça peut faire apparaitre des bugs étranges ou les faire disparaitre (dans tous les cas c'est la merde)

      On peut en dire autant du debuggeur, il y a aussi des bugs qui ne se produisent qu'en dehors du debuggeur.

      parce que savoir quand une variable est modifié et par ou (avoir la stack), est parfois essentiel à la correction d'un bug.

      C'est vrai mais honnetement ça ne m'arrive pour ainsi dire jamais , à par dans les cas où ça sent la corruption de mémoire , et là en général je commence par sortir valgrind

      parce que des traces trop verbeuses peuvent avoir un gros impact sur les perfs; l'appli sur laquelle je bosse fait des traces de plusieurs centaines de Mo à l'heure, et on essaye de retreindre…

      Il suffit de ne pas faire des traces monstrueuses, debugger au printf pour moi ça ne veut pas dire farcir chaque ligne de code avec un printf("prout oulala %d:%d\n", FILE,__LINE__) , tout comme je ne commence pas par lacher un milliard de breakpoints avant de demarrer gdb

      Parce que changer une valeur sans avoir à tout recompiler permet de tester des cas plus larges.

      Certes

      Parce que dès qu'on joue un petit peu avec des theads, les traces ont un impacte dans l’ordonnancement.

      Le debuggeur aussi , d'autant plus si tu as été obligé de recompiler ton code avec les optimisations un peu moins fortes pour avec des stack trace qui ressemblent à quelque chose

      • [^] # Re: Oui

        Posté par  . Évalué à 2.

        On peut en dire autant du debuggeur, il y a aussi des bugs qui ne se produisent qu'en dehors du debuggeur.

        Surtout quand c'est des bugs dépendant des optimisations du compilateur et que compiler en mode optimisé rend le débuggage aléatoire.

        • [^] # Re: Oui

          Posté par  (site web personnel) . Évalué à 2.

          En général, cela te donne une bonne idée du bug en question : un mix unsigned/signed, un décalage de bit mal fait, un integer overflow, etc…

          "La première sécurité est la liberté"

      • [^] # Re: Oui

        Posté par  . Évalué à 2.

        Parce que dès qu'on joue un petit peu avec des theads, les traces ont un impacte dans l’ordonnancement.

        Le debuggeur aussi.

        Je plussoie.
        C’est d’ailleurs pour cette raison que des gens s’amusent à tripoter GDB pour donner ça, ce qui permet d’avoir des trucs un minimum reproductibles quand on debug du multithread.

  • # synthèse

    Posté par  . Évalué à 3.

    Pour synthétiser les discussions, les outils de debuggage sont (par ordre approximatif d'utilisation décroissante) :
    - printf
    - gdb
    - strace
    - valgrind
    - cppcheck

    J'ai mis des noms précis, mais je veux indiquer la catégorie d'outil. Donc quand je mets "printf", il faut lire "printf et équivalent (System.out.println, etc.)", et pareil pour les autres.

    Chacun de ces outils est un debugger. Donc pour répondre à la question initiale "Un debugger est-il indispensable ?", la réponse est oui.

  • # Bien sûr que non!

    Posté par  . Évalué à 2.

    Mon code ne contiens aucun bug, uniquement des fonctionnalités non documentées :D

    Plus sérieusement, j'utilise de moins en moins printf, je préfère balancer des exceptions, qui elles font se terminer le programme avec un message qui indique quelle condition n'a pas été respectée.
    Il se peut même que je rattrape l'exception si le problème n'est pas trop grave pour afficher un simple avertissement, ou mettre le problème dans le journal.

    Quelqu'un a dis plus haut que le message est parfois délicat à trouver… je ne suis pas d'accord. L'exception peut parfois être lisible pour un utilisateur, mais je ne suis pas sûr que ce soit le but: je préfère quelque chose qui m'indique quelle condition à merdé. Si c'est du runtime_error, alors on peut savoir et dire ce qu'il s'est passé: fichier de configuration corrompu ou manquant, problème de connexion réseau, plus de papier dans l'imprimante… et la, l'utilisateur peut régler le problème lui-même.
    Mais si c'est dû à un bug, il n'a pas à comprendre, de toute façon il ne pourra rien y faire. Il faut uniquement lui donner une procédure pour envoyer un rapport d'erreur correcte, et pourquoi pas l'envoyer de façon automatisée.

    Le débogueur est toujours utile, mais il y a des cas ou il ne fonctionne pas (j'ai déjà vu des breakpoint faire planter l'application), et ceux disponibles sous linux ont des interfaces tout de même assez pénibles selon moi.
    Sinon, j'aime aussi beaucoup l'idée de l'analyse statique, mais je n'ai pas eu l'occasion d'essayer de tels outils malheureusement.

    • [^] # Re: Bien sûr que non!

      Posté par  . Évalué à 3.

      Sinon, j'aime aussi beaucoup l'idée de l'analyse statique, mais je n'ai pas eu l'occasion d'essayer de tels outils malheureusement.

      Jusqu'à maintenant, le meilleur moyen de faire de l'analyse statique que j'ai trouvé est de compiler en -Werror et d'activer un max de warnings, et celà avec un maximum de compilo différents (dans mon cas pour l'instant GCC, CLang, MSVC).
      Ça permet vraiment d'éviter une très grosse partie de bugs potentiels.

      Je compile même avec le support C++11 de temps en temps pour utiliser le nouveau keyword "override". (avec un #if __cplusplus >= 201103L pour ne l'activer qu'en C++11).

      D'ailleurs ça m’intéresserait si certains d'entre vous sont dans le même cas de connaître vos flags de compil (surtout les warnings).

      Pour ma part j'utilise avec GCC et CLang: -Werror -Wchar-subscripts -Wformat -Wformat-y2k -Wformat-security -Winit-self -Wmissing-braces -Wparentheses -Wsequence-point -Wswitch -Wunused-label -Wunused-variable -Wuninitialized -Wfloat-equal -Wcast-align -Wsign-compare -Waddress -Wextra -Wnon-virtual-dtor -Wreturn-type -Wno-write-strings

      et avec MSVC (les noms sont beaucoup moins parlant): /WX /W4 /wd4100 /wd4702 /wd4389 /wd4355 /wd4211 /wd4355 /wd4065 /wd4505

      • [^] # Re: Bien sûr que non!

        Posté par  . Évalué à 2.

        Pour gcc:

        -pedantic -Wall -Wextra -Wformat=2 -Winit-self -Wcast-qual -Wcast-align -Wconversion -Wwrite-strings -Wstrict-prototypes -Wfloat-equal -Wshadow -Wredundant-decls -Wundef -Wbad-function-cast -Wold-style-definition -Wdouble-promotion -Wmissing-declarations -Wmissing-include-dirs -Wswitch-default -Wlogical-op -Wnested-externs -Wunreachable-code -Wpadded
        
        

        Pour g++ (un peu moins fourni, je code moins souvent en C++):

        -pedantic -Wall -Wextra -Wcast-qual -Wcast-align -Wconversion -Wsign-conversion -Wshadow -Wredundant-decls -Wundef -Wold-style-cast -Wdouble-promotion -Wfloat-equal -Woverloaded-virtual -Wmissing-include-dirs -Wswitch-default -Wlogical-op -Wno-long-long -Wunreachable-code -Wpadded
        
        

        Je tiens à signaler que Wpadded produit pas mal de bruit, donc je ne l'active pas toujours (c’est souvent juste pour info, je l’active de temps en temps).

        Bon faudrait que je mette mes flags à jour. Avec les dernières versions de gcc, il y en a probablement des nouveaux qui sont intéressants.

        Pour clang, c’est bien plus simple (même options pour le C et le C++):

        -Weverything -fcatch-undefined-behavior -ftrapv
        
        
      • [^] # Re: Bien sûr que non!

        Posté par  . Évalué à 1.

        (dans mon cas pour l'instant GCC, CLang, MSVC).

        Dans mon souvenir icc était pas mal aussi sur ce plan là.

        Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

  • # Il y à quand même quelques cas où...

    Posté par  . Évalué à 1.

    …le point d'arrêt est fatalement plus efficace que n'importe quel VDD.

    Les appels récursifs, ou, les boucles sans conditions.

    Ah c'est l'horreur de rentrer dans ce genre de séquence qui bugue que sous certaines conditions uniquement après un certain nombre d'itérations…
    Là, je regrette de ne pas pouvoir poser un point d'arrêt….
    Me reste plus que ma tête.

  • # 7 ans plus tôt...

    Posté par  (site web personnel) . Évalué à 2.

    https://linuxfr.org/users/krunch/journaux/printf-debugging-considered-harmful

    Donc sinon perso j'aime beaucoup le concept de debugger système comme SystemTap ou DTrace qui sont généralement moins intrusif pour l'application que gdb et permettent de creuser là où d'autres outils en sont incapable.

    pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.