Publicité
+ Répondre à la discussion
Page 1 sur 3 123 DernièreDernière
Affichage des résultats 1 à 20 sur 47
  1. #1
    Membre chevronné
    Avatar de D[r]eadLock
    Inscrit en
    mai 2002
    Messages
    504
    Détails du profil
    Informations personnelles :
    Âge : 34

    Informations forums :
    Inscription : mai 2002
    Messages : 504
    Points : 682
    Points
    682

    Par défaut Comment bien debugger son code ?

    Suite a la recrudescence de cas problematique, voici le fruit d'une petite reflexion. Si vous avez d'autre choses a ajouter

    Tout d'abord pour debugger un programme, il faut avoir les idees clair deja quant au programme, c'est a dire :
    - qu'est-ce qu'il fait
    - comment il le fait

    et pour aider a cela, rien de tel que du code clair :
    - indentation (on decale le code de quelques espaces apres un if, etc.)
    - commentaire (telle fonction fait ceci, telle variable contient le resultat, etc.)
    - fractionnement des "fonctions" (faire des fonctions generique plutot que d'avoir une fonction de 150 lignes super chiant a debugger)

    Ensuite, pour les erreurs de compilations,
    - compiler avec le maximum de warnings (-Wall pour gcc). Et comprendre ces warnings : un bon programme ne doit avoir aucun warning : un warning est succeptible de causer une erreur.
    - utiliser man (manuel en ligne pour voir la syntaxe des primitives des librairies) (rappel: 'man fprintf' sous linux/unix), ou l'aide en ligne si disponible.
    - reflechir au sens des instructions : pourquoi on fait ceci, cela etc.

    Enfin, quand vous ne voyez pas l'erreur (et c'est comprehensible), afin de simplifier la tache de ceux qui vont vous aider, il faut specifier au maximum les erreurs rencontrees, en donnant:
    - le message d'erreur,
    - l'environement utilise (win/linux, compilo, librairies...)
    - la ligne du code ou se produit cette erreur
    - le code des structures et autres definitions si besoin est (pour montrer les types des donnees utilisees)

    Il n'est pas necessaire :
    - de donner le code complet (sauf si demande expressement)

    Remarque, lorsque du code est donne, il doit l'etre entre les balises [code ] et [/code ]

  2. #2
    gl
    gl est déconnecté
    Rédacteur/Modérateur

    Homme Profil pro
    Inscrit en
    juin 2002
    Messages
    2 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : juin 2002
    Messages : 2 077
    Points : 4 192
    Points
    4 192

    Par défaut

    Petit complement, non pour debugger (quoique) mais pour limiter le risque de bug :
    - toujours tester les valeurs de retours des fonctions
    - fermer immediatement une accolade puis mettre le code ensuite (ca evite de se retrouver avec un programme qui ne compile pas, et c'est assez penible de tout reprendre pour voir ou se situe le pb)
    - de meme lors d'une allocation, ecrire la ligne de desallocation, puis le traitement entre les deux.

    En passant une petite remarque sur un des conseils de D[r]eadLock :
    "fractionnement des fonctions", c'est une remarque tout a faite vrai dans le cas de la programmation sur PC, mais pour avoir programmer sur des systemes embarques avec rlativement peu de memoire (peu de pile en particulier), le trop grand fractionnement peu etre source dans certains cas de bug memoire (depassement de pile) assez penible a debugger.

  3. #3
    Membre chevronné
    Avatar de D[r]eadLock
    Inscrit en
    mai 2002
    Messages
    504
    Détails du profil
    Informations personnelles :
    Âge : 34

    Informations forums :
    Inscription : mai 2002
    Messages : 504
    Points : 682
    Points
    682

    Par défaut

    Pour gvim :
    - set showmatch, pour faire clignoter l'accolade/la parenthese/le crochet ouvrant correspondant quand on en ecrit un/une fermant.

    - % (en mode commande) sur une accolade/parenthese/crochet ouvrant ou fermant pour aller a celui correspondant.

    D'autre part, la syntaxe highlight permet de ne pas trop se planter sur les mots cles, mais surtout, permet de reconnaitre les chaines de caracteres et donc de toutes les fermer.

  4. #4
    Membre confirmé

    Inscrit en
    juin 2002
    Messages
    97
    Détails du profil
    Informations forums :
    Inscription : juin 2002
    Messages : 97
    Points : 271
    Points
    271

    Par défaut

    (quelques notions sont en double avec le premier post)

    D'une façon générale, quand une erreur de compilation ou d'exécution imcompréhensible ne semble pas avoir de rapport avec l'endroit du source où elle survient, elle n'en a effectivement pas et est la conséquence d'une erreur silencieuse précédente.
    Autrement dit, quand le système remarque que quelque chose ne va pas, il est déjà trop tard !

    L'exemple typique pour la compilation est le ";" manquant à la fin d'une struct/class. Très vicieux si elle est dans un header, car l'erreur est signalée dans un autre fichier !
    L'exemple typique pour l'exécution est l'écrasement de mémoire. Par exemple, "char* copie= strcpy(malloc(strlen(source)),source);" oublies le +1 nécessaire au '\0' terminal.


    Pour ne pas faire d'erreurs, le mieux est de comprendre ce que l'on fait (facile à dire).


    Pour éviter les situations indéboguables, le développement incrémental est très bien:
    Cmmencer avec un truc ridiculement simple mais qui marche.
    Rajouter une petite fonctionnalité, tester.
    Rajouter tout le reste pareil: petit à petit, en testant à chaque fois.


    Pour capturer les erreurs, un moyen simple est de protéger son code avec plein d'assertions.
    Elles ne sont actives qu'en mode déboguage.
    Code :
    1
    2
    3
    4
    5
    6
    7
    #include <assert.h>
     
    void maFonc(char* pc, int len){
    	assert(pc != NULL); //cette fonction ne gère pas le rien, merci !
    	assert(len<1000000; //à mon humble avis, ceci n'est pas une longueur de chaîne...
    	//...
    }

    Des nids à erreurs:
    Structures if/else/switch imbriquées trop complexes. Un bogue peut se terrer dans une branche rarement parcourue.
    Fonctions trop longues. Signe que des concepts distincts sont mal indentifiés/séparés.
    Variables utilisées à des endroits très distants. Signe d'inter-dépendance excessive du code.


    L'éditeur est ton ami, il t'aide à ne pas faire de fautes si:
    -Il dispose d'une coloration syntaxique riche.
    -Il propose l'auto-complétion (avec correction majuscule/minuscule please).
    -Il permet de (ré)indenter automatiquement le code.

    Le compilateur se doit de donner des messages d'erreurs compréhensibles, en désignant l'endroit exact où se trouve le problème dans la ligne.
    Régler les alertes au maximum est une bonne pratique.

    Le débogueur est indispensable. Il doît être capable de:
    -Éxécuter le code source pas à pas, en montrant les valeurs des variables et la pile d'appel des fonctions.
    -Gérer des points d'arrêts (conditionnels c'est mieux).
    -Pister les écrasements/fuites de mémoire.

    Un environnement de éveloppement intégré (EDI) regrouppant ces trois-là, plus l'appel de la documentation et d'autres outils, c'est un must !

    La librairie a un rôle à jouer aussi.
    Si elle est de qualité, elle est blindée d'assertions.
    Son interface devrait être intuitive et peu sujette au erreurs.


    Erreurs de débutants fréquentes

    Divers:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class A{
    }//";" manquant
     
    typedef struct truc truc_t //";" manquant
     
    do{
    	//...
    }while(test) //";" manquant
     
    if(test); //";" en trop (pareil avec for et while)
    	action1(); //pas imbriquée logiquement (à cause du ";")
    	action2(); //pas imbriquée logiquement (il faut englober les deux avec {})
    Erreurs de macros:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #define PI = 3.141596 //erreur: "=" erroné
    double Var = PI*3 ; //Ce code...
    double Var = = 3.141596*3 ; //devient ceci! "syntax error : '='"
     
    #define PI 3.141596; //erreur: ";" erroné
    double Var = PI*3 ; //Ce code...
    double Var = 3.141596;*3 ; //devent ceci ! "illegal indirection"
     
    #define CARRE(a) a*a; //erreur: insuffisant
    int Var3 = CARRE(Var1+Var2) ;//Ce code...
    int Var3 = Var1+(Var2*Var1)+Var2 ;//équivaut à ceci !
    int Var3 = ~CARRE(Var1) ;//Ce code...
    int Var3 = (~Var1)*Var1 ;//équivaut à ceci !
    #define CARRE(a) ((a)*(a)); //corrigé
    Erreurs de syntaxe:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    char* ptr1, ptr2; //erreur: ptr2 est de type char
    char *ptr1, *ptr2; //solution1
    typedef char* charptr;
    charptr ptr1, ptr2;//solution2 
     
    if(Var=EOF) action(); //erreur: "=" au lieu de "=="
    if(EOF=Var) action(); //solution 1, mettre la constante devant provoque une erreur de compilation
    //solution 1, augmenter le niveau de warning
     
    if(/*test*/);
    	/*action*/;
    while(/*test*/);
    	/*action*/;
    for(/*init*/;/*test*/;/*++*/);
    	/*action*/;
    //erreur: ";" termine l'instruction conditionelle sur une instruction nulle.
    //solutions:
    //-réindentation automatique (montre la faute en alignant /*action*/ avec le reste).
    //-augmenter le niveau de warning et mettre "NULL" quand on a vraiment une instruction nulle.
     
    switch (Var) {
    	case 0: /*action*/; //erreur: manque "break"
    	default: /*action*/;
    }
    //solutions:
    //-mettre le commentaire "//no break" quand c'est intentionnel.
    //augmenter le niveau de warning (ne marche pas partout).
    Erreurs de logique:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    int Var2 = Var1+1<<8; //erreur de précédence d'opérateur...
    int Var2 = Var1+(1<<8); //...équivaut à ceci (+256).
    int Var2 = (Var1+1)<<8; //solution: rendre explicite l'ordre si douteux, ou quand on mélange les types d'opérateurs.
     
    int Array[20];
    Array[20] = Var; //erreur: surpassement, tableau de 20 va de 0 à 19.
    Array[i]= i++; //erreur, i peut être incrémenté avant ou après l'indiçage.
     
    char* Msg = "Message";
    Msg[0]= 'm'; //erreur, les chaînes littérales sont des constantes !
    char* cptr = (char*)malloc(strlen(Msg)); //erreur: manque +1 au strlen pour le '\0' terminal.
     
    putchar("A"); //erreur, "A" est une chaîne, 'A' est un caractère
     
    if(/*test1*/)
    	if(/*test2*/){
    		/*action1*/;
    	}; //ce ";" superflu termine le if imbriqué...
    	else //...ce else concerne donc le premier if !
    		/*action2*/;
    Erreurs d'E/S:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    cVar = getchar();
    gets(cArray); //erreur: [Entrée] validant getchar est resté et donne une ligne vide
    while(getchar() != '\n'); //Solution, intercaller ceci pour vider le tampon
    fflush(stdin); //ceci est de comportement indéfini, à éviter !
     
    //idem avec la méthode C++
    cin >> cVar;
    cin.ignore(INT_MAX, '\n');
    cin.getline(cArray,cArraySize);
    "J'ai toujours rêvé d'un ordinateur qui soit aussi facile à utiliser qu'un téléphone. Mon rêve s'est réalisé : je ne sais plus comment utiliser mon téléphone."-Bjarne Stroustrup
    www.stroustrup.com

  5. #5
    Nouveau Membre du Club
    Inscrit en
    décembre 2002
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : décembre 2002
    Messages : 29
    Points : 32
    Points
    32

    Par défaut

    petits ajouts et correctifs :

    Citation Envoyé par gl
    toujours tester les valeurs de retours des fonctions
    oui effectivement, mais plus particulierement malloc, surtout ne jamais oublier de tester un malloc, et aussi les file descriptor, toujours tester les open ou fopen et autres...

    Citation Envoyé par gl
    de meme lors d'une allocation, ecrire la ligne de desallocation, puis le traitement entre les deux
    pas necessairement, des fois on veux allouer et ne pas free tout de suite, exemple avec les listes chainers

    il faut juste faire tres attention a la gestion de la memoire

    Citation Envoyé par Musaran
    Par exemple, "char* copie= strcpy(malloc(strlen(source)),source);"
    je trouve ce genre d'ecriture assez dangereuse, et je la deconseille aux debutants, declarez plutot toute vos variables en debut de fonctions, et commencer apres votre code sans ne plus declarer de variables apres, certains compilateurs (GCC le fait) n'autorise plus la declaration de variables apres que des instructions on ete saisie.

    enfin de plus je ne preconise pas l'emploie d'un malloc directement dans une fonction, ceci entraine la perte d'un pointeur et donc une fuite de memoire, pas forcement source d'erreur, mais bon mieux vaut quand meme faire les choses bien.

    il est preferable de separer le code clairement plutot que d'imbriquer trop de fonctions, car ceci peut mener a une erreur de parenthese, voir a une erreur de prioriter dans la gestion du code.

    ...

    Citation Envoyé par Musaran
    Code :
    assert(len<1000000; //à mon humble avis, ceci n'est pas une longueur de chaîne...
    tu as oublier la parenthese fermante de ton assert, mais ceci n'est rien, juste un petit signalement

    bon sinon une assez bonne methode de debugging, pour ceux qui travail sur les outils arcailliques, ou pour ceux qui travail sur de bons outils mais qui prefere la methode a la flamme bien moyennageuse la technique du printf debugging est tres bonne, par exemple dans un bout de code qui plante, vous cherchez ou cela plante, tres simple...

    vous placez un printf sur chaques lignes, et cela donne ceci :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int    ma_fonction(int val)
    {
        char    *str;
     
        printf("1\n");
        str = "crabe";
        printf("2\n");
        str[42] = 'k';
        printf("3\n");
        return (val);
    }
    ainsi vous avez a l'ecran afficher : 1 et 2, ainsi, si vous avez un plantage avant de voir le 3, vous savez tout de suite ou se trouve precisement l'erreur

    voila, pour des questions n'hesitez surtout pas a poster dans le forum
    Fatalis
    "La femme est le chef-d'oeuvre de Dieu, surtout quand elle a le diable au corps" Alphonse Allais

  6. #6
    Candidat au titre de Membre du Club
    Inscrit en
    janvier 2003
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : janvier 2003
    Messages : 18
    Points : 13
    Points
    13

    Par défaut

    Quelques rectificatifs/précisions :

    Citation Envoyé par Fatalis
    je trouve ce genre d'ecriture assez dangereuse, et je la deconseille aux debutants, declarez plutot toute vos variables en debut de fonctions, et commencer apres votre code sans ne plus declarer de variables apres, certains compilateurs (GCC le fait) n'autorise plus la declaration de variables apres que des instructions on ete saisie.
    La norme ANSI C ne prévoit pas qu'il soit possible de déclarer des variables au milieu du code. En C, les variables peuvent être uniquement déclarées juste après une accolade ouvrante. Donc normallement , seul un compilateur C++ compilera du code (C ou C++) contenant des déclarations de variables au sein des instructions.

    Citation Envoyé par Fatalis
    vous placez un printf sur chaques lignes, et cela donne ceci :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Code:
    int    ma_fonction(int val)
    {
        char    *str;
     
        printf("1\n");
        str = "crabe";
        printf("2\n");
        str[42] = 'k';
        printf("3\n");
        return (val);
    }
    ainsi vous avez a l'ecran afficher : 1 et 2, ainsi, si vous avez un plantage avant de voir le 3, vous savez tout de suite ou se trouve precisement l'erreur
    Ceci est en effet une bonne habitude à prendre. Mais attention ! La fonction printf est "bufferisée" donc le texte n'est pas immédiatement affiché à l'écran (ou dans le fichier ...). Donc, je pense qu'il est préférable d'utiliser fprintf dirigée sur stderr pour les informations de débogage. (Cette fonction est disponible sous Unix, je ne sais pas si c'est le cas sous DOS/Win)

  7. #7
    gl
    gl est déconnecté
    Rédacteur/Modérateur

    Homme Profil pro
    Inscrit en
    juin 2002
    Messages
    2 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : juin 2002
    Messages : 2 077
    Points : 4 192
    Points
    4 192

    Par défaut

    Citation Envoyé par lsdInside
    Ceci est en effet une bonne habitude à prendre. Mais attention ! La fonction printf est "bufferisée" donc le texte n'est pas immédiatement affiché à l'écran (ou dans le fichier ...). Donc, je pense qu'il est préférable d'utiliser fprintf dirigée sur stderr pour les informations de débogage. (Cette fonction est disponible sous Unix, je ne sais pas si c'est le cas sous DOS/Win)
    fprintf fait partie du C standard donc normalement disponible partout, mais elle est elle aussi bufferisee

  8. #8
    Membre confirmé

    Inscrit en
    juin 2002
    Messages
    97
    Détails du profil
    Informations forums :
    Inscription : juin 2002
    Messages : 97
    Points : 271
    Points
    271

    Par défaut

    Citation Envoyé par lsdInside
    La norme ANSI C ne prévoit pas qu'il soit possible de déclarer des variables au milieu du code.
    En C99 c'est désormais possible.
    "J'ai toujours rêvé d'un ordinateur qui soit aussi facile à utiliser qu'un téléphone. Mon rêve s'est réalisé : je ne sais plus comment utiliser mon téléphone."-Bjarne Stroustrup
    www.stroustrup.com

  9. #9
    Membre chevronné

    Homme Profil pro Thierry
    Ingénieur développement logiciels
    Inscrit en
    avril 2002
    Messages
    121
    Détails du profil
    Informations personnelles :
    Nom : Homme Thierry
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : avril 2002
    Messages : 121
    Points : 606
    Points
    606

    Par défaut

    Citation Envoyé par gl
    Citation Envoyé par lsdInside
    Ceci est en effet une bonne habitude à prendre. Mais attention ! La fonction printf est "bufferisée" donc le texte n'est pas immédiatement affiché à l'écran (ou dans le fichier ...). Donc, je pense qu'il est préférable d'utiliser fprintf dirigée sur stderr pour les informations de débogage. (Cette fonction est disponible sous Unix, je ne sais pas si c'est le cas sous DOS/Win)
    fprintf fait partie du C standard donc normalement disponible partout, mais elle est elle aussi bufferisee
    L'avantage de stderr est que les les messages sont tout de même affichés même en cas de plantage contrairement a stdout ! cela permet donc de savoir le plantage a réellement eu lieu !

  10. #10
    Membre habitué Avatar de Metal Tom
    Profil pro Thomas P.
    Inscrit en
    avril 2003
    Messages
    119
    Détails du profil
    Informations personnelles :
    Nom : Thomas P.
    Âge : 32

    Informations forums :
    Inscription : avril 2003
    Messages : 119
    Points : 110
    Points
    110

    Par défaut

    Citation Envoyé par gRRosminet
    L'avantage de stderr est que les les messages sont tout de même affichés même en cas de plantage contrairement a stdout ! cela permet donc de savoir le plantage a réellement eu lieu !
    Il me semble que si on fait un fflush(stdout); juste après l'écriture dans stdout ça affiche bien même en cas de plantage (saut si c'est pendant l'écriture dans stdout naturellement).
    Tom

  11. #11
    Membre à l'essai
    Inscrit en
    mai 2003
    Messages
    30
    Détails du profil
    Informations forums :
    Inscription : mai 2003
    Messages : 30
    Points : 21
    Points
    21

    Par défaut

    Citation Envoyé par Metal Tom
    Il me semble que si on fait un fflush(stdout); juste après l'écriture dans stdout ça affiche bien même en cas de plantage (saut si c'est pendant l'écriture dans stdout naturellement).

    IL y a aussi la fonction C perror() est c'est la simplicite meme pour afficher les messages d'erreurs.

  12. #12
    Membre habitué Avatar de Metal Tom
    Profil pro Thomas P.
    Inscrit en
    avril 2003
    Messages
    119
    Détails du profil
    Informations personnelles :
    Nom : Thomas P.
    Âge : 32

    Informations forums :
    Inscription : avril 2003
    Messages : 119
    Points : 110
    Points
    110

    Par défaut

    Ouais, elle donne plus d'informations sur l'erreur. Elle traduit la variable errno.
    Le message peut être récupéré grâce à sys_errlist[errno]. errno et sys_errlist sont des variables de stdlib.h qu'il faut déclarer (sans oublier le extern) pour les utiliser.
    Tom

  13. #13
    Responsable technique

    Avatar de Anomaly
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    juin 2003
    Messages
    8 435
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : juin 2003
    Messages : 8 435
    Points : 24 703
    Points
    24 703

    Par défaut

    Citation Envoyé par Metal Tom
    IL y a aussi la fonction C perror() est c'est la simplicite meme pour afficher les messages d'erreurs.
    Oui, mais c'est destiné à afficher le contenu de errno... Or, tu n'en as pas toujours besoin, là il s'agissait de faire une sorte de trace du programme.

    Quant à printf sur stdout, normalement tout \n envoyé vide le buffer... Ceci dit envoyer le message sur stderr permet d'être sûr que le texte sera affiché, car stderr n'est pas bufferisé (c'est une caractéristique du flux d'erreur et non de fprintf), de plus, sous Unix uniquement, il est possible de dissocier la sortie normale du processus de la sortie d'erreur, grâce aux opérateurs de redirection > et 2>.

  14. #14
    Expert Confirmé

    Homme Profil pro
    Inscrit en
    juillet 2003
    Messages
    2 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ardennes (Champagne Ardenne)

    Informations forums :
    Inscription : juillet 2003
    Messages : 2 077
    Points : 2 557
    Points
    2 557

    Par défaut

    Lut
    Si bien que l'on ne s'est pas quel debugger il faut préférer:Vous utilisez lequel?
    Souos windows comme sous linux?

  15. #15
    Invité régulier
    Inscrit en
    mars 2004
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : mars 2004
    Messages : 9
    Points : 6
    Points
    6

    Par défaut ahhh stderr

    Citation Envoyé par Metal Tom
    Citation Envoyé par gRRosminet
    L'avantage de stderr est que les les messages sont tout de même affichés même en cas de plantage contrairement a stdout ! cela permet donc de savoir le plantage a réellement eu lieu !
    Il me semble que si on fait un fflush(stdout); juste après l'écriture dans stdout ça affiche bien même en cas de plantage (saut si c'est pendant l'écriture dans stdout naturellement).
    stderr est toujours affiché tout simplement parce que cette sortie n'est pas bufferisée, contrairement à stdout C'est effectivement pour cela qu'il vaut mieux envoyer ses messages de debug vers cette sortie. En fait je donnerais meme deux raisons :
    - Vous les voyez immédiatement apparaître à l'écran (et non pas après l'arrivée d'un \n ou un truc du genre pour stdout)
    - Vous pouvez ne garder que les sorties de stderr avec une syntaxe de lancement du genre :
    Code :
    monprogramme > /dev/null
    @++

  16. #16
    Invité régulier
    Inscrit en
    mars 2004
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : mars 2004
    Messages : 9
    Points : 6
    Points
    6

    Par défaut debugger

    Citation Envoyé par Gnux
    Lut
    Si bien que l'on ne s'est pas quel debugger il faut préférer:Vous utilisez lequel?
    Souos windows comme sous linux?
    Je ne développe presque jamais sous windows, mais je ne suis pas sûr qu'il existe des debuggers performants existants à la fois sous linux et sous windows.

    J'utilise ddd sous linux qui utilise, je crois gdb. (comme bcp d'autres)

    @++

  17. #17
    Membre émérite Avatar de Caine
    Inscrit en
    mai 2004
    Messages
    1 024
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : mai 2004
    Messages : 1 024
    Points : 951
    Points
    951

    Par défaut Une méthode éprouvée.

    Bonjour,
    Mon expérience professionnelle et personnelle m’a appris que bien debuguer consiste à prévoir cette phase essentielle dès le départ d’un projet. Voici les trois phases d’un bon debug :

    1) Dés l’étude du cahier des charges, quand on prend connaissance des fonctionnalités de l’application, il est utile de prévoir les tests globaux du projet suivant les contraintes, les objectifs et l’ergonomie de l’application.
    2) Lors de la conception, plus approfondie, mais surtout avant d’avoir les premiers jets de lignes de code, élaborer une vision de l’ensemble des tests unitaires, ainsi que de l’ensemble des tests d’intégration de l’application.
    3) Maintenant les tests listés, commencer à développer les utilitaires de tests.

    Pourquoi se lancer dans l’étude des tests si tôt ? Avant même d’avoir les premières lignes de codes ? La raison est simple : Une fois lancé dans le développement proprement dit, on perd la vision de l’ensemble. Il y a le risque d’oublier des interactions entre modules, ou bien encore carrément de tester certaines valeurs triviales. C’est pourtant sur ces points que l’utilisateur final (un client, un prof…) ne manquera pas de tomber sans forcer le jour J.
    De plus si dés la conception, vous affinez la liste des tests d’intégrations, vous gagnerez du tant lorsqu’un test unitaire échouera au cours de l’évolution du logiciel. En effet, plutôt que de recommencer l’ensemble des tests suite à une correction dans un modules, vous serez quels tests d’intégration rejouer à coup sûr.

    Sans rentrer dans le détail pour ce qui est des tests unitaires (choisir errorno, fprintf avec stderr…), voici quelques conseils :
    1) Ecrire un code clair : Indenter les sources proprement, écrivez des commentaires précis, pertinents et concis (pas besoin de romans).
    2) Tout bloc de code ne servan,t qu’au debug (même la plus petite déclaration) doit être inclus dans un bloc conditionnel.
    Code :
    1
    2
    3
    4
    5
    6
     
    #ifdef _debug#else#endif
    3) Vérifier systématiquement les arguments des fonctions et procédures avec des assertions. Si vous connaissez la preuve algorithmique, n’hésitez pas en faire usage.
    4) Préférez des test automatisés à des tests manuels.

    Enfin, une fois cette phase achevée, n’oubliez pas des tests de monter en charge de l’application ou de performance : Charge CPU, Vérifier qu’il n’y a pas de fuites mémoires …

    Bon débug à tous, et toutes

  18. #18
    Candidat au titre de Membre du Club
    Inscrit en
    mars 2005
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 27
    Points : 14
    Points
    14

    Par défaut

    juste un complément pour faire de belles traces...

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    #define USE_TRACE
     
    /* macro de trace
     * UTILISATION: TRACE(("%s", string))
     * ne pas oublier les doubles parenthèses
     *---------------------------------------------------
     */
    #ifdef USE_TRACE
    # define TRACE(a) do		\
        { printf("TRACE: ");	\
          printf a;			\
          fflush(stdout);		\
          break;			\
        }while(1);
    #else
    # define TRACE(a)
    #endif
    et l'utilisation ...

    Code :
    1
    2
     
    TRACE(("Error %d : texte %s", err, "Complément"));
    Ce qui est interessant ici c'est que vous pouvez à la volée préciser votre format pour le printf.

    'Content de peu n'a rien à craindre'
    http://jm.marino.free.fr

  19. #19
    Rédacteur
    Avatar de Emmanuel Delahaye
    Profil pro
    Inscrit en
    décembre 2003
    Messages
    14 505
    Détails du profil
    Informations personnelles :
    Âge : 57
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : décembre 2003
    Messages : 14 505
    Points : 19 420
    Points
    19 420

    Par défaut

    Citation Envoyé par xylo
    Code :
    1
    2
    3
    4
    5
    6
    7
     
    # define TRACE(a) do		\
        { printf("TRACE: ");	\
          printf a;			\
          fflush(stdout);		\
          break;			\
        }while(1);
    C'est pas, c'est sans ';'...

    C'est drôlement compliqué... Tiré de ma bibliothèque:

    http://emmanuel-delahaye.developpez....b/ed/inc/sys.h
    Code :
    1
    2
    3
    4
    5
    6
     
    /* printf programmable (debug)
     * usage : PRINTF (("Hi, I'm %d years old\n", 48))
     */
    #define PRINTF(s)                   \
       printf s
    Pas de Wi-Fi à la maison : CPL

    Des infos sur la programmation et le langage C:
    http://bien-programmer.blogspot.com/
    http://www.bien-programmer.fr/
    http://bien-programmer.forum-actif.net/forum.htm

  20. #20
    Invité régulier
    Inscrit en
    septembre 2004
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : septembre 2004
    Messages : 5
    Points : 5
    Points
    5

    Par défaut

    Citation Envoyé par Gnux
    Lut
    Si bien que l'on ne s'est pas quel debugger il faut préférer:Vous utilisez lequel?
    Souos windows comme sous linux?
    gdb
    dbx sous solaris quand gdb n'est pas dispo (et que je ne suis pas root).

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •