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

C Discussion :

sprintf et taille de buffer


Sujet :

C

Vue hybride

koktel_dfr sprintf et taille de buffer 23/03/2007, 12h06
fearyourself Juste parce que cela ne... 23/03/2007, 12h10
Franck.H De plus, même si ta chaîne... 23/03/2007, 12h11
Franck.H Cela peut très bien passer... 23/03/2007, 12h12
Thierry Chappuis D'ailleurs, si le nom de ton... 23/03/2007, 12h15
souviron34 C'est absolument normal........ 23/03/2007, 12h28
koktel_dfr ok, merci pour vos réponses,... 23/03/2007, 12h38
Franck.H Si tu as la possibilité de... 23/03/2007, 12h44
souviron34 Tu as plusieurs manières de... 23/03/2007, 12h46
koktel_dfr He bien merci à tout les... 23/03/2007, 12h57
gl Sans revenir sur les... 23/03/2007, 18h50
souviron34 +10 On est vraiment c.ns... 24/03/2007, 01h01
Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    182
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 182
    Par défaut sprintf et taille de buffer
    Je souhaire écrire une fonction qui crée un fichier de log dont le nom serait : <nom du programme><date systeme>.log, la date devant être sous le format ddmmaaaa.

    J'utilise pour cela un buffer et la fonction sprintf.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    //Déclaration du buffer
    char logName[21];
     
    sprintf(logName,"ExpMicros%.2d%.2d%.4d.log",tb->tm_mday,(tb->tm_mon)+1,(tb->tm_year)+1900);
    printf("logName: %s %d", logName,strlen(logName));
    Le nom de mon fichier de log a toujours une taille de 21, c'est la raison pour laquelle mon buffer est à 21. Mais, ce qui est étrange c'est que lorsque je déclare mon buffer par char logName[1] ou n'importe quelle valeur en dessous de 21, mon programme ne plante pas et fonctionne parfaitement... alors que d'après ce que j'ai pu lire partout il fallait s'assurer que le buffer soit d'une taille suffisante sous peine de plantage... mais je n'ai aucun plantage !

    Je précise que strlen(logName) me renvoie bien 21 malgré l'éventuel char logName[1];

    Si quelqu'un pouvait m'expliquer ce mystère...

  2. #2
    Expert confirmé

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Par défaut
    Juste parce que cela ne plante pas ne veut pas dire que ton programme est juste.

    C'est en mettant une taille plus petite que tu risque un jour d'avoir un problème et tu y passeras des heures pour retrouver l'endroit où tu as mis une taille trop petite.

    D'ailleurs, je te conseille de passer à une taille plus grande que juste le strict minimum. Il suffit que tu veuille ajouter une lettre devant ton nom et tu risqueras un plantage qui sera aussi compliqué à comprendre.

    Jc

  3. #3
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    De plus, même si ta chaîne fait 21, il ne faut pas oublier un char en plus pour le zéro de fin de chaîne !
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  4. #4
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Citation Envoyé par koktel_dfr
    Si quelqu'un pouvait m'expliquer ce mystère...
    Cela peut très bien passer sur un système mais pas sur un autre ... comportement indéterminé !?
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  5. #5
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    D'ailleurs, si le nom de ton fichier de log a toujours une taille de 21 (comme retourné par la fonction strlen()), la taille de ton buffer doit au minimum être de 22 caractères de manière à pouvoir contenir le caractère nul de fin de chaîne.

    EDIT: grillé

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  6. #6
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par koktel_dfr
    . Mais, ce qui est étrange c'est que lorsque je déclare mon buffer par char logName[1] ou n'importe quelle valeur en dessous de 21, mon programme ne plante pas et fonctionne parfaitement... alors que d'après ce que j'ai pu lire partout il fallait s'assurer que le buffer soit d'une taille suffisante sous peine de plantage... mais je n'ai aucun plantage !

    Je précise que strlen(logName) me renvoie bien 21 malgré l'éventuel char logName[1];

    Si quelqu'un pouvait m'expliquer ce mystère...
    C'est absolument normal..... Le printf écrit ses 22 caractères à partir de l'adresse initiale. N'ayant pas déclaré la bonne longueur, il écrit au delà de ce qui a été reservé.

    Par conséquent, si c'est la dernière instruction du programme, ça ne porte pas à conséquence.

    Par contre, dans quasiment tous les autres cas, si tu as d'autres variables, si c'est une fonction, si tu as un tableau ou une variable décalrée après la déclaration de la chaîne (sur la pile), etc.... ce sera écrasé....

    Par exemple, si tu déclarais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char Nom[10] ;
    char Ligne[20] ;
    Et que tu commences à remplir Ligne, il est fort probable que Ligne serait écrasée lors du remplissage de Nom. Et si ce n'était pas le cas, quelque chose quelque part serait écrasée (ce qui serait situé dans le segment mémoire où le programme est loadé à l'adresse Nom+10).

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    182
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 182
    Par défaut
    ok, merci pour vos réponses, je comprends mieux maintenant.
    Il me faut donc un buffer de 21+1 pour éviter tout problèmes éventuels, même si je n'en ai pas pour le moment...

    Autre question mais totalement liée a celle-ci... le taille du nom de mon fichier de log sera toujours fixe quoi qu'il advienne, soit 21 caractère. Mais il n'en sera pas de même pour les lignes de mon log qui elles varierons en taille en fonction de l'erreur constaté (et qui sera écrite dans le fichier de log...).

    Voici le code concernant l'écriture des lignes de mon log :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    FILE *f_out;
    char logLine[200];
     
    sprintf(logLine,"[ERROR] %s ---> %s - %s\n",functionName, errorDescription,error);
     
    f_out = fopen(logFile,"a");
    fputs(logLine, f_out);
    fclose(f_out);
    Je trouve plutot dommage de devoir déclarer un buffer de taille 200 sachant que ma ligne de log peut ne pas dépasser les 50... aurait-il un moyen de gérer ca dynamiquement. Déterminer la taille de la ligne est facile avec strlen(), mais que mettre au niveau de la déclaration de logLine ?

    Merci.

  8. #8
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Si tu as la possibilité de retrouver la taille totale de la chaîne à mettre dans ton fichier avant sa construction avec sprintf, oui tu peux sans problème faire une allocation dynamique:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    char * logLine = malloc (taille_de_la_chaine + 1);
     
    if (logLine != NULL)
    {
       ...
    }
    ...
    Sans oublier alors dans ce cas de libérer le buffer une fois que tu n'en as plus besoin
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  9. #9
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par koktel_dfr
    Je trouve plutot dommage de devoir déclarer un buffer de taille 200 sachant que ma ligne de log peut ne pas dépasser les 50... aurait-il un moyen de gérer ca dynamiquement. Déterminer la taille de la ligne est facile avec strlen(), mais que mettre au niveau de la déclaration de logLine ?

    Merci.
    Tu as plusieurs manières de faire.

    En voici 1 totalement dynamique :

    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
     
    FILE *f_out=NULL;
    char *logLine=NULL;
     
    logLine = malloc ( (strlen(functionName) + strlen(errorDescription) + strlen(error) + 19 + 1 ); 
    /* le 19 est pour les blancs plus [ERROR] + la fleche + le \n qui peut être CR LF ou CR */
    if ( logLine != NULL )
    {
      sprintf(logLine,"[ERROR] %s ---> %s - %s\n",functionName, errorDescription,error);
     
      f_out = fopen(logFile,"a");
      if ( f_out != NULL )
        {
           fputs(logLine, f_out);
           fclose(f_out);
        }
       else
             fprintf(stderr,"%s",logLine);
       free(logLine);
     }
    else
      fprintf(stderr,"[ERROR] %s ---> %s - %s\n",functionName, errorDescription,error);

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    182
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 182
    Par défaut
    He bien merci à tout les deux, rapides en plus

    Vous me faites gagner de précieuses heures de travail, je teste ca tout de suite et je vous tiens au courant.

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    182
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 182
    Par défaut
    Ton code fonctionne parfaitement souviron34.

    De plus, merci d'avoir tout deux précisé pour le test du retour de la fonction malloc()... je n'y aurait même pas pensé... même si je pense que, sauf erreur de ma part il doit être plutot rare qu'un malloc() ne puisse pas se faire.

    Par contre tant que j'y suis j'ai une dernière question, c'est juste un détail, je me permet donc de la poser ici plutot que d'ouvrir un autre topic...

    Je suis sous Windows(oui je sais, la honte...), lorsque j'ouvre mon fichier de log, généré avec le précédent code à l'aide du (au combien fabuleux...) bloc-note j'ai droit a un espèce de carré plutot qu'a un retour a la ligne... alors que lorsque je l'ouvre dans context(l'editeur de code que j'utilise) je n'ai aucun problème. A quoi cela est-il du et peut on corriger cela au niveau du code ?

    Promis, après ca je ne vous embête plus

  12. #12
    gl
    gl est déconnecté
    Rédacteur

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

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par koktel_dfr
    Voici le code concernant l'écriture des lignes de mon log :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    FILE *f_out;
    char logLine[200];
     
    sprintf(logLine,"[ERROR] %s ---> %s - %s\n",functionName, errorDescription,error);
     
    f_out = fopen(logFile,"a");
    fputs(logLine, f_out);
    fclose(f_out);
    Je trouve plutot dommage de devoir déclarer un buffer de taille 200 sachant que ma ligne de log peut ne pas dépasser les 50... aurait-il un moyen de gérer ca dynamiquement. Déterminer la taille de la ligne est facile avec strlen(), mais que mettre au niveau de la déclaration de logLine ?

    Merci.
    Sans revenir sur les remarques pertinentes et les corrections qu'ont deja fournit d'autre posteurs, quel est l'interet de la chaine temporaire ? Si tu ne l'utilises pas en dehors de cet extrait, le code suivant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    FILE *f_out;
    f_out = fopen(logFile,"a");
    if(f_out != NULL)
    {
       fprintf(f_out, "[ERROR] %s ---> %s - %s\n", functionName, errorDescription,error);
       fclose(f_out);
    }
    est bien plus simple.

  13. #13
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    +10

    On est vraiment c.ns de pas y avoir pensé plus tôt

    MAis bon, on regardait pas ça.. Mais quand même..

    Bravo

Discussions similaires

  1. Taille de buffer dépassé pour DBMS_LOB
    Par Loizo dans le forum PL/SQL
    Réponses: 10
    Dernier message: 09/02/2009, 17h34
  2. [Sockets] Rendre la taille du buffer infinie ?
    Par Danny Blue dans le forum C#
    Réponses: 2
    Dernier message: 05/07/2008, 19h25
  3. augmentation de la taille du buffer MS SQL Server 2000
    Par lachgar_omar dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 06/12/2007, 21h29
  4. [TCP] Taille de buffer, et fonction send()
    Par phraides dans le forum Développement
    Réponses: 4
    Dernier message: 03/06/2007, 14h45
  5. Réponses: 39
    Dernier message: 27/03/2007, 20h25

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