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 :

Etrange problème avec un fprintf


Sujet :

C

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Août 2006
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 199
    Points : 116
    Points
    116
    Par défaut Etrange problème avec un fprintf
    Bonsoir à tous,

    J'ai developpé un petit programme de traitement d'image ppm/pgm sous linux. Ca fonctionne sans problème sous linux mais lorsque je passe sous windows je rencontre des erreurs etranges. J'ai tenté d'isoler le problème et il semble que le bug vienne d'un simple fprintf. Pour être plus précis voici le morceau de code, très simple je vous l'accorde, incriminé.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    FILE *fichier = NULL;
    fichier = fopen( nomFichier , "wb" );
    fprintf(fichier,"P5\n256 256\n255\n");
    fclose(fichier);
    Je code sous code::blocks avec le toolkit mingw et lorsque je place mon curseur juste avant le fprintf, que j'execute en mode debug, puis j'execute la suite du programme (tjs en mode debug) ça marche.

    Autre observation : J'avais des accents et des espaces dans le chemin du dossier contenant le programme et bien que je ne les utilisais pas directement dans le programme (je n'utilise que des chemins relatif qui ne sortent pas du dossier), le fait de les enlever a fait marcher le fprintf. J'ai donc ajouté le fwrite initialement présent à la suite du fprintf et là rebug.

    J'avoue que là, je suis un peu dépassé

    ps:le fichier est bien créé.

    edit : ajout du flux dans le fprintf (erreur de frappe)

  2. #2
    Rédacteur

    Avatar de khayyam90
    Homme Profil pro
    Architecte de système d’information
    Inscrit en
    Janvier 2004
    Messages
    10 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Architecte de système d’information

    Informations forums :
    Inscription : Janvier 2004
    Messages : 10 369
    Points : 40 164
    Points
    40 164
    Par défaut
    Bien le bonsoir,

    sortant tout droit du man,
    int fprintf (FILE *stream, const char *format, ...);
    le premier argument est un FILE* et pas directement le contenu à y mettre

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Août 2006
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 199
    Points : 116
    Points
    116
    Par défaut
    A oups je m'excuse pour la faute de frappe.

    Mais hélas pour moi j'ai bien respecté la synthaxe du fprintf et le problème semble plus sournois. Par ailleur je rappelle que le code compile et que le programme fonctionne sous linux

  4. #4
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par f56bre
    je rencontre des erreurs etranges. J'ai tenté d'isoler le
    Ce code est incomplet. On ne sait pas ce que tu as oublié. <stdio.h>est obligatoire ici.
    Il faut tester l'ouverture avant d'appeler les autres fonction f*().
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
       if (fichier != NULL)
       {
          ...
    Pas de Wi-Fi à la maison : CPL

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Août 2006
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 199
    Points : 116
    Points
    116
    Par défaut
    Je sais que je propose ici un code quelque peu simplifié. Cependant j'ai bien inclut le stdio.h et je teste bien l'ouverture du fichier avec une sortie de la fonction en cas d'erreur. Voici le code complet de la fonction. Comme vous pouvez le voir je n'utilise pas le paramètre, je créé un nom de fichier dans la fonction, et comme vous pouvez le voir cette fonction semble sortie tout droit d'un exemple de cours de C.

    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
    char * RempliFichierBinaire( const ContenuFichier * contenuFichier )
    {
    	const char * nomFichier = "fichierbinaire.ppm";
    	FILE * fichier = NULL;
     
    	fichier = fopen( nomFichier , "wb" );
    	if( fichier == NULL )
    		return NULL;
     
     
    	fprintf( fichier , "P5\n256 256\n255\n" );
     
    	//fwrite( contenuFichier->image->t , sizeof(unsigned char) , contenuFichier->image->hauteur*contenuFichier->image->largeur , fichier );
     
        fclose(fichier);
     
    	return nomFichier;
    }

  6. #6
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par f56bre
    Je sais que je propose ici un code quelque peu simplifié. Cependant j'ai bien inclut le stdio.h et je teste bien l'ouverture du fichier avec une sortie de la fonction en cas d'erreur. Voici le code complet de la fonction. Comme vous pouvez le voir je n'utilise pas le paramètre, je créé un nom de fichier dans la fonction, et comme vous pouvez le voir cette fonction semble sortie tout droit d'un exemple de cours de C.
    Ceci fonctionne (je ne sais pas pourquoi il est si difficile d'obtenir du code compilable et testable... personne ne sait donc ce qu'est un test unitaire ?):
    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
     
    #include <stdio.h>
    #include <stdlib.h>
    typedef struct
    {
       int dummy;
    }
    ContenuFichier;
     
    int RempliFichierBinaire (const ContenuFichier * contenuFichier)
    {
       const char *nomFichier = "fichierbinaire.ppm";
       FILE *fichier = NULL;
       fichier = fopen (nomFichier, "wb");
       if (fichier == NULL)
          return 1;
       fprintf (fichier, "P5\n256 256\n255\n");
       fclose (fichier);
       return 0;
    }
     
    int main (void)
    {
       const contenuFichier = 
       {
          0
       };
       int err = RempliFichierBinaire (contenuFichier);
     
       if (err)
       {
          puts ("erreur");
       }
       return 0;
    }
    et j'obtiens un fichier contenant ceci :
    soit en hexa :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    00000000h: 50 35 0A 32 35 36 20 32 35 36 0A 32 35 35 0A    ; P5.256 256.255.
    Ce qui me parait tout à fait conforme aux attentes.
    Pas de Wi-Fi à la maison : CPL

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Août 2006
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 199
    Points : 116
    Points
    116
    Par défaut
    Est il possible qu'à la suite d'une allocation dynamique on rencontre ce genre de problèmes. En effet j'ai chargé une image à partir d'un fichier ppm texte dans une structure par allocation dynamique, juste avant de lancer cette fonction. Ce qui est byzarre c'est que si j'enlève l'appel à la fonction ci-dessus et ajoute un affichage du contenu de la structure ce que j'obtient est nickel.

    De plus, encore une fois, tout fonctionne nickel sous linux.

    Et enfin en enlevant la fonction de chargement d'image et en ne lançant que la fonction ci-dessus elle marche nickel (le résultat est conforme aux attentes comme dirait Mr Delahaye )

    Je vais voir du côté de l'allocation mais cela ressemble t'il à quelque chose que vous avez déjà rencontré?

    Une dernière question. Lorsque l'on alloue dynamiquement de la memoire pour une structure les membres de celle-ci sont ils initialisés à 0 (ou NULL pour les pointeurs). Il semble que ce soit le cas sous linux mais de toute façon je le fait par sécurité.

  8. #8
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par f56bre
    Est il possible qu'à la suite d'une allocation dynamique on rencontre ce genre de problèmes.
    Si un comportement indéterminé s'est produit, tout peut arriver. Les deux problèmes principaux sont :
    • utilisation d'un pointeur non initialisé
    • débordement de tableau.

    De plus, encore une fois, tout fonctionne nickel sous linux.
    Ce qui ne prouve rien.
    Une dernière question. Lorsque l'on alloue dynamiquement de la memoire pour une structure les membres de celle-ci sont ils initialisés à 0 (ou NULL pour les pointeurs). Il semble que ce soit le cas sous linux mais de toute façon je le fait par sécurité.
    Non, pas du tout. Et all-bits-to-0 n'est pas forcément ce qu'il faut pour obtenir des pointeurs NULL. Il faut soit initialiser 'à la main', soit utiliser des init statiques et faire une copie...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
       T *p = malloc (sizeof *T);
       if (p != NULL)
       {
          static const T z = {0};
          *p = z;
          /* ... */
    Pas de Wi-Fi à la maison : CPL

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Août 2006
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 199
    Points : 116
    Points
    116
    Par défaut
    J'ai un début de réponse.

    Un fichier ppm commence par un code de 2 caractères (P2,P5, etc...). J'ai donc un char* de taille 3 dans lequel je fais un gets de 3 char. Si je passe la taille du char* de 3 à 2 le bug expliqué ci dessus disparait. Par contre pas moyen de scanner les 2 caractères avec un gets de 2 char . Ou en tout cas lorsque j'affiche la chaine scannée je n'ai que le "P".

    Pourtant un gets scanne le nombre de char scécifié sauf s'il rencontre avant un '\0' ou '\n'. Dans mon cas après le chiffre il doit y avoir un '\n'.

  10. #10
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par f56bre
    J'ai un début de réponse.

    Un fichier ppm commence par un code de 2 caractères (P2,P5, etc...). J'ai donc un char* de taille 3 dans lequel je fais un gets
    STOP

    gets() est un bug potentiel qu'il ne faut pas utiliser dans les nouveaux développements. Apprendre à utiliser fgets() correctement.

    http://emmanuel-delahaye.developpez....tes.htm#saisie
    http://emmanuel-delahaye.developpez....s.htm#fichiers

    D'autre part, c'est quoi un "char * de taille 3" ? char *tab[3]; ?
    Pas de Wi-Fi à la maison : CPL

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Août 2006
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 199
    Points : 116
    Points
    116
    Par défaut
    oups je me suis encore craqué, c'est des fgets que j'utilise pour lire dans le fichier et les char* de taille 3 sont des tableau de char de 3 éléments.

    merci pour les liens je vais lire ça.

  12. #12
    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 : 47
    Localisation : Suisse

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par f56bre
    oups je me suis encore craqué, c'est des fgets que j'utilise pour lire dans le fichier et les char* de taille 3 sont des tableau de char de 3 éléments.

    merci pour les liens je vais lire ça.
    Un tableau de caractères et un char *, c'est pas tout à fait la même chose.

    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++

    +

  13. #13
    Membre régulier
    Profil pro
    Inscrit en
    Août 2006
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 199
    Points : 116
    Points
    116
    Par défaut
    Pour moi c'est exactement la même chose. Dans tous les cas c'est un pointeur vers un char. Seul peut différer la façon dont la mémoire peut être allouée derrière.

  14. #14
    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 : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par f56bre
    Pour moi c'est exactement la même chose. Dans tous les cas c'est un pointeur vers un char. Seul peut différer la façon dont la mémoire peut être allouée derrière.
    deux contre exemples:

    * sizeof : sizeof applique a un pointeur, donnera toujours la meme taille (celle d'un pointeur) alors que sizeof applique a un tableau fournit la taille reelle du tableau.
    * affectation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char a;
    char* ptr;
    char tab[10];
     
    ptr = &a;      // Correct
    tab = &a;      // Invalide

  15. #15
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par f56bre
    Pour moi c'est exactement la même chose. Dans tous les cas c'est un pointeur vers un char. Seul peut différer la façon dont la mémoire peut être allouée derrière.
    Bah non... Un tableau n'est pas un pointeur... Et le type d'un tableau de char n'est certainement pas char *. Ca se saurait... Par contre, char * est le type de l'adresse d'un élément du tableau, oui.

    http://emmanuel-delahaye.developpez.....htm#char_star
    Pas de Wi-Fi à la maison : CPL

Discussions similaires

  1. Problème avec fprintf
    Par farid0031 dans le forum MATLAB
    Réponses: 2
    Dernier message: 06/04/2012, 18h00
  2. problème avec la fonction fprintf
    Par Flaherty Mc Coillean dans le forum MATLAB
    Réponses: 2
    Dernier message: 01/05/2008, 16h13
  3. Débutant - Problème avec fprintf()
    Par Ryuzaki dans le forum Windows
    Réponses: 3
    Dernier message: 22/03/2008, 15h56
  4. Débutant - Problème avec fprintf et backspace
    Par Ryuzaki dans le forum Windows
    Réponses: 0
    Dernier message: 22/03/2008, 14h01
  5. Problème avec la mémoire virtuelle
    Par Anonymous dans le forum CORBA
    Réponses: 13
    Dernier message: 16/04/2002, 16h10

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