IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

GTK+ avec C & C++ Discussion :

Affichage de chaine de caractères et différence de comportement linux/win32


Sujet :

GTK+ avec C & C++

  1. #1
    Membre confirmé
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2009
    Messages
    61
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2009
    Messages : 61
    Par défaut Affichage de chaine de caractères et différence de comportement linux/win32
    Bonjour/bonsoir à tous/toutes,
    une petite question pour essayer de comprendre une différence
    de comportement entre mon programme Gtk+ compilé sous Vista (Codeblocks) et sous ma bonne Fedora.
    Il m'est tout d'abord important de préciser, que sous Linux comme sous Windows, je n'ai aucune erreur 'fatale' à l'exécution ... mais mais mais ...
    Avant d'aller plus loin, mon programme est un programme d'analyse scientifique (dispo ici http://isaacs.sourceforge.net),
    à un certain point durant l'exécution je demande l'affichage dans un Gtk_Text_View du résultat d'un calcul,
    l'affichage diffère sous Win32 et Linux ... je m'excuse par avance de la longueur du texte à venir ...

    1) Résultat sous Linux (affichage Ok)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    Shortest path ring statistics:
     
     Average number of rings per configuration: 115.900000 +/- 24.973097
     Average number of rings with n > 20 nodes which potentially exist: 135.800000 +/- 26.469269
     n     Rc(n)    Rc[All](n)    +/-       Pn(n)       +/-       Pmax(n)     +/-       Pmin(n)     +/-
     3   0.004651   0.004651   0.003562   0.010853   0.008130   0.488095   0.155371   1.000000   0.000000
     4   0.083333   0.083333   0.015205   0.295736   0.040199   0.508681   0.075866   0.996369   0.008366
     5   0.004651   0.004651   0.002451   0.022093   0.011122   0.547619   0.082685   0.911111   0.145297
     6   0.057364   0.057364   0.013770   0.229070   0.040752   0.629735   0.067917   0.666030   0.105880
     7   0.001163   0.001163   0.002616   0.006202   0.013201   0.619048   0.067344   0.706349   0.213254
     8   0.030233   0.030233   0.007029   0.117054   0.031794   0.582700   0.110923   0.469954   0.112416
     9   0.004651   0.004651   0.005420   0.018992   0.023216   0.725725   0.200212   0.426149   0.206935
    10   0.018992   0.018992   0.012318   0.066279   0.033911   0.559826   0.186853   0.344088   0.113461
    11   0.001163   0.001163   0.002616   0.007752   0.016444   0.661616   0.164277   0.494949   0.071425
    12   0.053101   0.053101   0.023474   0.116279   0.041060   0.666946   0.113125   0.390984   0.139641
    13   0.001550   0.001550   0.003269   0.001550   0.003269   1.000000   0.000000   0.000000   0.000000
    14   0.044961   0.044961   0.030311   0.069767   0.046296   0.767157   0.125960   0.284305   0.094722
    15   0.012791   0.012791   0.009503   0.015891   0.015871   0.521368   0.260955   0.110256   0.216445
    16   0.032171   0.032171   0.029237   0.054651   0.044248   0.648796   0.088311   0.195941   0.133427
    17   0.005814   0.005814   0.007806   0.005814   0.007589   0.866667   0.217307   0.000000   0.000000
    18   0.056977   0.056977   0.041103   0.026744   0.020627   0.878171   0.153111   0.039583   0.098214
    19   0.008915   0.008915   0.010971   0.007752   0.015504   0.933333   0.149071   0.107692   0.215385
    20   0.026744   0.026744   0.014894   0.045736   0.030943   1.000000   0.000000   0.280113   0.123251
    1) Résultat sous Win32 (affichage pas Ok du tout)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Shortest path ring statistics:
     
     Average number of rings per configuration: 115.900000 +/- 24.973097
     Average number of rings with n > 20 nodes which potentially exist: 135.800000 +/- 26.469269
     n     Rc(n)    Rc[All](n)    +/-       Pn(n)       +/-       Pmax(n)     +/-       Pmin(n)     +/-
     3   0.004651   0.004651   0.003562   0.010853   0.008130   0.488095   0.155371   1.000000   0.000000
     4   0.083333   0.083333   0.015205   0.295736   0.040199   0.508681   0.075866   0.996369   0.008366
     5   0.004651   0.004651   0.002451   0.022093   0.011122   0.547619   0.082685   0.911111   0.145297
     6   0.057364   0.057364   0.013770   0.229070   0.040752   0.629735   0.067917   0.666030   0.105880
     7   0.001163   0.001163   0.002616   0.006202   0.013201   0.619048   0.067344   0.706349   0.213254
     8   0.030233   0.030233   0.007029   0.117054   0.031794   0.582700   0.110923   0.469954   0.112416
     9   0.004651   0.004651   0.005420   0.018992   0.023216   0.725725   0.200212   0.426149   0.206935
    10   0.018992
    Pour faire simple sous Win32 de nombreuses informations qui devraient être affichées ne le sont pas (arrêt de l'affichage à la 10 ligne sur 20 ... )
    et je ne sais pas pourquoi ... voici mon code (je l'ai raccourci un peu pour ce message)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    void printrings_ (int * idnodes,  int * nodes, double nc[ringsize*2], double pna[ringsize*2],
                     double rmax[ringsize*2], double rmin[ringsize*2],
                     double ectrc[ringsize*2], double ectpna[ringsize*2],
                     double ectmax[ringsize*2], double ectmin[ringsize*2],
                     double * rpstep, double * ectrpst, double * nampat, double * ectampat)
    {
      int i, j;
      char * value;
      char * nelt;
      char ra[22]=" n     Rc(n)    Rc[";
      char rb[36]="](n)   Pn(n)     Pmax(n)    Pmin(n)";
      char rc[78]="](n)    +/-       Pn(n)       +/-       Pmax(n)     +/-       Pmin(n)     +/-";
      char re[20]=" ring statistics:\n";
      char rf[4]="   ";
      char rg[2]=" ";
      char rh[35]=" Average number of rings with n > ";
      char ri[33]=" nodes which potentially exist: ";
      char rj[6]=" +/- ";
      char rk[45]=" Average number of rings per configuration: ";
      char rd[42]=" * only ABAB rings have been considered\n";
      char rl[47]=" * homopolar bonds can not shorten the rings\n";
      GtkWidget * info;
      GtkTextBuffer * buffer = NULL;
      GtkTextIter bStart;
      GtkTextIter bEnd;
      size_t rtot=10;
      char * ritot;
      char * tritot;
     
      j = * idnodes;
      j = j-1;
      rtot+=strlen(retl);
    // un grand passage dans lequel je prépare la taille de mémoire à allouer ..
    // une fois cela fait j'alloue la mémoire nécessaire ...
      ritot = g_malloc(rtot*sizeof*ritot);
    /// puis je copie le tout dans ma chaine de caractères 
      strcpy(ritot,retl);
      strcat(ritot,trc[search]);
     ...
    // Enfin je veux afficher le tout, en prenant des précautions
      tritot = g_malloc(rtot*sizeof*tritot);
    #ifdef G_OS_WIN32
      wsprintf (tritot, "%s", ritot);
    #else
      snprintf (tritot, rtot, "%s", ritot);
    #endif
      g_free(ritot);
      g_print("%s", tritot);
      info = (GtkWidget *) gtk_builder_get_object (BuilderGtk, "TextInfo");
      buffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(info));
      gtk_text_buffer_get_start_iter (buffer, &bStart);
      gtk_text_buffer_get_end_iter (buffer, &bEnd);
      gtk_text_buffer_insert (buffer, &bEnd, tritot, -1);
      gtk_text_view_set_buffer (GTK_TEXT_VIEW(info), buffer);
      g_free(tritot);
    }
    Le code précédent, plus précisément la partie finale donne les résultats présentés plus haut respectivement sous Linux et Win32.

    Il m'est possible de corriger le tire et d'obtenir un affichage correct sous Win32 avec les changements suivants:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    //  tritot = g_malloc(rtot*sizeof*tritot);
    //#ifdef G_OS_WIN32
    //  wsprintf (tritot, "%s", ritot);
    //#else
    //  snprintf (tritot, rtot, "%s", ritot);
    //#endif
    //  g_free(ritot);
      g_print("%s", ritot);
      info = (GtkWidget *) gtk_builder_get_object (BuilderGtk, "TextInfo");
      buffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(info));
      gtk_text_buffer_get_start_iter (buffer, &bStart);
      gtk_text_buffer_get_end_iter (buffer, &bEnd);
      gtk_text_buffer_insert (buffer, &bEnd, ritot, -1);
      gtk_text_view_set_buffer (GTK_TEXT_VIEW(info), buffer);
      g_free(ritot);
    Toutes vos lumières sont les bienvenues, je ne suis pas un grand programmeur et j'aimerais bien comprendre le pourquoi du comment ... merci d'avance !

  2. #2
    Membre Expert
    Homme Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 259
    Par défaut
    Tous ces mallocs, strncpy, ... font un peu peur, je te recommanderais d'utiliser g_strdup et g_strdup_printf, g_str_concat, ... au maximum, ça t'évite de gérer les tailles d'allocation mémoire toi même (et donc ça limite les risques d'erreur)

  3. #3
    Membre émérite
    Inscrit en
    Avril 2007
    Messages
    667
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Avril 2007
    Messages : 667
    Par défaut
    Salut,

    Tu ne verifie aucun retour de malloc(), il suffit que ta machine sous windows manque de memoire et tu as ton explication

    Ensuite, je ne comprends pas vraiment la difference entre ritot et tritot, tu alloues la meme quantite de memoire puis copies le contenue de ritot dans tritot...

    Et enfin, j'ai telecharge les sources pour lire le code en entier et je rejoins teuf13, tu abuses vraiment du malloc, strcat, strcpy...
    Ce serait plus lisible d'utiliser snprintf et donc plus facile d'identifier les bugs.
    Par exemple tu peux remplacer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
          value=g_strdup_printf("%2d",i+1);
          rtot+=strlen(value);
          g_free(value);
          rtot+=strlen(rf);
          value=g_strdup_printf("%lf",nc[i]/natomes);
          rtot+=strlen(value);
          g_free(value);
          rtot+=strlen(rf);
          value=g_strdup_printf("%lf",nc[i]/(* nodes));
          rtot+=strlen(value);
          g_free(value);
          rtot+=strlen(rf);
          value=g_strdup_printf("%lf",pna[i]/(* nodes));
          rtot+=strlen(value);
          g_free(value);
          rtot+=strlen(rf);
          value=g_strdup_printf("%lf",rmax[i]);
          rtot+=strlen(value);
          g_free(value);
          rtot+=strlen(rf);
          value=g_strdup_printf("%lf",rmin[i]);
          rtot+=strlen(value);
          g_free(value);
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
          char buf[1024];
          snprintf(buf, 1024, "%2d%lf%lf%lf%lf%lf", i+1,nc[i]/natomes,pna[i]/(* nodes), pna[i]/(* nodes),rmax[i], rmin[i]);
     rtot+=strlen(buf);
    Deuxieme exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
          value=g_strdup_printf("%d",i+1);
          strcat(ritot,value);
          g_free(value);
          strcat(ritot, rf);
          value=g_strdup_printf("%lf",nc[i]/natomes);
          strcat(ritot,value);
          g_free(value);
    vs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sprintf(ritot, "%d%s%lf", i+1, rf, nc[i]/natomes);

  4. #4
    Membre Expert
    Homme Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 259
    Par défaut
    Citation Envoyé par tonton fred Voir le message
    Et enfin, j'ai telecharge les sources pour lire le code en entier et je rejoins teuf13, tu abuses vraiment du malloc, strcat, strcpy...
    Ce serait plus lisible d'utiliser snprintf et donc plus facile d'identifier les bugs.
    Par pitié, non! Pas de s.printf, c'est vraiment trop source d'erreur!

    Citation Envoyé par tonton fred Voir le message

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
          char buf[1024];
          snprintf(buf, 1024, "%2d%lf%lf%lf%lf%lf", i+1,nc[i]/natomes,pna[i]/(* nodes), pna[i]/(* nodes),rmax[i], rmin[i]);
     rtot+=strlen(buf);
    Il vaut beaucoup mieux utiliser
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
        char *buf =  g_strdup_printf("%2d%lf%lf%lf%lf%lf", i+1,nc[i]/natomes,pna[i]/(* nodes), pna[i]/(* nodes),rmax[i], rmin[i]);
    Deuxieme exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
          value=g_strdup_printf("%d",i+1);
          strcat(ritot,value);
          g_free(value);
          strcat(ritot, rf);
          value=g_strdup_printf("%lf",nc[i]/natomes);
          strcat(ritot,value);
          g_free(value);
    vs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sprintf(ritot, "%d%s%lf", i+1, rf, nc[i]/natomes);
    Non, il vaut beaucoup mieux l'écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ritot = g_strdup_printf ("%s%d%s%lf", i+1, ritot, rf, nc[i]/natomes);
    (si ritot pointe sur de la mémoire malloc-ée, il faut passer par une variable intermédiaire pour libérer la mémoire utilisée)

  5. #5
    Membre confirmé
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2009
    Messages
    61
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2009
    Messages : 61
    Par défaut Merci !
    Merci pour tout, j'ai besoin d'être éduqué sur la bonne manière
    d'afficher des chaînes de caractères en langage C ... je vais
    corriger mes erreurs ... n'hésitez pas à m'en apprendre
    d'avantage

  6. #6
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Par défaut
    Citation Envoyé par tonton fred Voir le message
    Tu ne verifie aucun retour de malloc(), il suffit que ta machine sous windows manque de memoire et tu as ton explication
    Tu te trompes, g_malloc fait une assertion quand il n'y a plus de mémoire. L'équivalent à malloc est g_try_malloc, qui lui renvoie NULL s'il n'a pas réussi à allouer la mémoire demandée. Et je confirme ce que dit teuf, il faut utiliser g_strdup_printf qui est beaucoup plus simple à utiliser.

  7. #7
    Membre émérite
    Inscrit en
    Avril 2007
    Messages
    667
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Avril 2007
    Messages : 667
    Par défaut
    Citation Envoyé par teuf13 Voir le message
    Par pitié, non! Pas de s.printf, c'est vraiment trop source d'erreur!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char buf[1024];
          snprintf(buf, 1024, "%2d%lf%lf%lf%lf%lf", i+1,nc[i]/natomes,pna[i]/(* nodes), pna[i]/(* nodes),rmax[i], rmin[i]);
    Il vaut beaucoup mieux utiliser
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
        char *buf =  g_strdup_printf("%2d%lf%lf%lf%lf%lf", i+1,nc[i]/natomes,pna[i]/(* nodes), pna[i]/(* nodes),rmax[i], rmin[i]);
    Dans le cas present, il n'y a pas de difference de syntaxe entre snprintf et g_strdup_printf, sauf que snprintf permet de travailler sur un tableau statique alors que g_strdup_printf oblige a utiliser un tableau dynamique:
    - strdup alloue de la memoire qu'il ne faut pas oublier de liberer
    - il faut gerer les cas ou l'allocation echoue ce qui n'est que tres rarement simple (annuler le traitement et continuer avec la valeur suivante? travailler sur des donnees que l'on sait fausses ou tronquees? crasher brutalement?).

    Dans le cas present, les tableaux sont internes a la fonction et de taille modeste (20 lignes, 10 colonnes) donc je ne vois aucun interet a passer par des tableaux dynamiques.

    Edit:
    Citation Envoyé par liberforce Voir le message
    Tu te trompes, g_malloc fait une assertion quand il n'y a plus de mémoire. L'équivalent à malloc est g_try_malloc, qui lui renvoie NULL s'il n'a pas réussi à allouer la mémoire demandée. Et je confirme ce que dit teuf, il faut utiliser g_strdup_printf qui est beaucoup plus simple à utiliser.
    g_strdup_printf peut echouer il me semble non?

  8. #8
    Membre Expert
    Homme Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 259
    Par défaut
    [quote=tonton fred;5128997]Dans le cas present, il n'y a pas de difference de syntaxe entre snprintf et g_strdup_printf, sauf que snprintf permet de travailler sur un tableau statique alors que g_strdup_printf oblige a utiliser un tableau dynamique:
    - strdup alloue de la memoire qu'il ne faut pas oublier de liberer

    Citation Envoyé par tonton fred Voir le message
    - il faut gerer les cas ou l'allocation echoue ce qui n'est que tres rarement simple (annuler le traitement et continuer avec la valeur suivante? travailler sur des donnees que l'on sait fausses ou tronquees? crasher brutalement?).
    Nope, cf la remarque de liberforce, la glib arrêtera de toute façon tout si tu n'as plus de mémoire

    Dans le cas present, les tableaux sont internes a la fonction et de taille modeste (20 lignes, 10 colonnes) donc je ne vois aucun interet a passer par des tableaux dynamiques.
    Il y a un énorme intérêt, tu n'as pas besoin de compter, compter et recompter pour allouer statiquement un buffer suffisamment grand, et ça, les gens se trompent tout le temps. Avec g_strdup_printf, pas d'erreur possible, donc vive g_strdup_printf. Oui, il y a quelques fois où snprintf peut être mieux, mais je préfère largement ne pas me prendre la tête et prendre une fonction qui ne va pas m'ajouter un bug obscur de corruption de mémoire parce que j'ai fait ue petite erreur dans une addition.

  9. #9
    Membre émérite
    Inscrit en
    Avril 2007
    Messages
    667
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Avril 2007
    Messages : 667
    Par défaut
    Citation Envoyé par teuf13 Voir le message
    Nope, cf la remarque de liberforce, la glib arrêtera de toute façon tout si tu n'as plus de mémoire
    Ok, je savais pas ca . Ben moi je prefere quand meme decider quoi faire en cas d'erreur plutot que de crasher betement.

    Citation Envoyé par teuf13 Voir le message
    Il y a un énorme intérêt, tu n'as pas besoin de compter, compter et recompter pour allouer statiquement un buffer suffisamment grand, et ça, les gens se trompent tout le temps. Avec g_strdup_printf, pas d'erreur possible, donc vive g_strdup_printf. Oui, il y a quelques fois où snprintf peut être mieux, mais je préfère largement ne pas me prendre la tête et prendre une fonction qui ne va pas m'ajouter un bug obscur de corruption de mémoire parce que j'ai fait ue petite erreur dans une addition.
    Je pense qu'on a un probleme de vocabulaire. Pour moi un tableau statique est de la forme
    Pas d'allocation ni de comptage et recomptage, juste un choix judicieux de taille au depart. Dans son cas, une ligne est composee de 10 colonnes de nombres, avec 8 characteres par nombre plus un separateur, 128 devrait suffire.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #define TAILLE_TAB 128
    ...
    char buf[TAILLE_TAB];
    ...
    snprintf(buf, TAILLE_TAB, ....);
    Je vois pas en quoi c'est plus prise de tete que g_strdup_printf.

    Ceci dit, ca n'aide que moyennement Slookeur: vu que les allocs ne peuvent pas echouer son probleme ne vient pas de la gestion de la memoire...

  10. #10
    Membre Expert
    Homme Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 259
    Par défaut
    Citation Envoyé par tonton fred Voir le message
    Pas d'allocation ni de comptage et recomptage, juste un choix judicieux de taille au depart.
    Oui, et tu le fais comment ton choix judicieux de la taille de départ ? En faisant des additions et des multiplications non ? "je veux afficher 11 lignes avec un %d de largeur max XXX, un %f de largeur max YYY, ça me fait donc 11 * (XXX + YYY + K)" avec des risques de te tromper quand tu évalues XXX, YYY, quand tu fais les additions, multiplications, ... et des bugs obscurs à la clé si tu te vautres. J'ai parlé de "recomptage", parce que le calcul de la taille de la chaîne est tellement sensible que je préfère le refaire plusieurs fois. A côté de ça, tu as g_strdup_printf où le seul truc auquel il faut prendre garde, c'est de libérer la chaîne qu'on te renvoie. Pour moi le choix est vite fait...

  11. #11
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Par défaut
    Je pense tout à fait comme teuf à ce sujet. Le débutant va se gourrer 50 fois sur du code de ce genre. Mais même l'utilisateur confirmé peut se faire avoir. Il y a plein d'erreurs courantes :

    1. sous-évaluer la taille du tableau initial
    2. changer la chaine de format en oubliant de vérifier si la taille du tableau est toujours suffisante
    3. avec snprintf, utiliser une taille différente de celle déclarée dans le tableau (hé oui, les débutants codent les valeurs en dur)


    Si des données à afficher proviennent de l'utilisateur, il peut dans certains se retrouver limité au niveau de l'affichage juste parce que le développeur n'a pas autorisé assez de place => crash avec sprintf, données tronquées avec snprintf.

    Le développeur a aussi plus de boulot, car en changeant la taille de la chaine de format pour mettre à jour le message, il peut introduire un bug dans le programme sans le savoir, parce que le tableau n'est plus assez grand pour contenir les données à afficher. Et cela peut arriver quand il y a plusieurs personnes qui travaillent sur le même logiciel, ou une même personne distraite, ou qui n'a pas touché à cette portion du code depuis longtemps. Tu te retrouves alors à devoir faire régulièrement des correctifs pour agrandir la taille des tableaux sous-évalués, et c'est rapidement agaçant : un développeur a autre chose à faire.

    Bref, avec sprintf ou snprintf, à chaque modification, il faut vérifier que tu ne casses rien. Avec g_strdup_printf, tu as un g_free une fois pour toute pour libérer la mémoire. Ensuite, tu peux modifier ta chaine de format à ta convenance, sans risque de casser quoi que ce soit.

    Pour conclure :
    • g_strdup_printf est à privilégier dans la majorité des cas, sans oublier de libérer ensuite la mémoire allouée.
    • snprintf est à utiliser quand la taille du message a très peu de chances de changer, ou bien quand le message est écrit très souvent, et que l'allocation/libération trop fréquente de mémoire par g_strdup_printf deviendrait ainsi trop nuisible aux performances
    • sprintf est à proscrire dans tous les cas, à cause des plantages et failles de sécurité qu'un débordement de tampon peut entraîner

  12. #12
    Membre confirmé
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2009
    Messages
    61
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2009
    Messages : 61
    Par défaut Merci (bis) !
    J'ai repris mon code en suivant vos conseils,
    non seulement celui-ci gagne en stabilité mais aussi, et cela
    n'est pas le moindre pour un programmeur, en clarté.

    C'est tout bon ça !

    Merci g_strdup_printf

    Une remarque supplémentaire, je pense en tant que novice, que le plus grand avantage de cette fonction est sa simplicité d'utilisation.

Discussions similaires

  1. sed - différence de comportement linux/AIX
    Par jack-ft dans le forum Shell et commandes POSIX
    Réponses: 7
    Dernier message: 02/07/2012, 17h12
  2. Affichage de chaine de caractère crypté
    Par Sephiroth.WIN dans le forum Sécurité
    Réponses: 1
    Dernier message: 25/06/2009, 22h26
  3. affichage de chaines de caractères
    Par yasinfo dans le forum Débuter avec Java
    Réponses: 7
    Dernier message: 04/04/2008, 19h10
  4. Affichage de chaine de caractére dans une Applet
    Par ibtbsoft dans le forum Applets
    Réponses: 3
    Dernier message: 03/12/2007, 01h51
  5. format affichage des chaines de caractères
    Par gorgonite dans le forum Langage
    Réponses: 3
    Dernier message: 10/05/2007, 22h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo