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

Visual C++ Discussion :

fstream => bug avec Visual c++ 2005 Express Edition ?


Sujet :

Visual C++

  1. #1
    Nouveau Candidat au Club
    Inscrit en
    Avril 2007
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 4
    Points : 1
    Points
    1
    Par défaut fstream => bug avec Visual c++ 2005 Express Edition ?
    Bonjour,

    j'utilise:
    - Windows XP SP2
    - Visual c++ 2005 Express Edition SP1

    Mon programme fonctionne parfaitement quand j'utilise: g++ 3.4.4.
    (Autant sous linux que sous windows)

    Le programme parcours le fichier et annalyse le texte.
    J'ai commencé avec une lecture caractère par caractère et je constate que de temps à autre, j'ai besoin de lire des lignes.
    ça ne pose pas de problème sur de très petit fichier ( < 4'096 caractères)

    Maintenant que mon parser est quasi fini, je constate que j'ai un soucis de temps en temps au moment où je dois revenir en arrière sur des fichiers plus grand que 4'096 caractères.


    Ce qui se passe:
    avec le debugger, j'ai pu constater que le fichier est parcourus par bloque de 4'096 caractères.
    Le programme dépasse se bloque de 4'096 en appelant la fonction get() ou getline().
    Ensuite le bug survient au moment où le programme doit revenir sur ces pas. J'utilise unget() plusieurs fois dans une boucle for (En raison d'un autre bug, voir rem ci-dessous).
    A ce moment le pointeur doit se perdre car je n'arrive plus à lire de caractères.


    A) Donc est-ce que c'est possible de modifier le nombre de caractères chargé ?
    (J'ai observé avec le debugger en me plaçant sur pointeur de type fstream puis j'ai parcourus les éléments suivants /+ _Filebuffer /+ _Myfile /+ _bufsize = 4096

    B) Est-ce qu'il est possible d'indiquer lorsque l'on ouvre le fichier qu'il soit totallement chargé en mémoire ? (fichier toujours plus petit que 10Mo)

    C) Est-ce qu'il y a qqch à modifier ou indiquer sous Visual C++ pour utiliser correctement la classe fstream ?


    REM:
    Ouvrir le fichier:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	string thefile = "nom du fichier";
    	fstream * pOpenedFile;
    	pOpenedFile = new fstream(thefile.c_str());
    lire un caractère:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	char readChar;
    	pOpenedFile->get(readChar);
    lire une ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	string strLine;
    	getline(*pOpenedFile,strLine);
    retour en arrière:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    	for(unsigned int i=0; i <= (strLine.length() - found ); i++)
    	{
    		pOpenedFile->unget();
    	}

    Si j'utilise pas les fonctions tellg() et seekg() c'est que les pointeurs retourné n'ont aucun sens lors que les fins de lignes sont signalées par Line Feed ( 0x0A ou '\n' )
    (Un autre bug sous Visual C++ 2005 enfin, j'en suis pas certain.)

    Et comme je souhaite pouvoir annalyser des fichiers texte au format UNIX ou Dos, je ne me limite pas au fin de ligne: Carriage Return et Line Feed ( 0x0D 0x0A ou "\r\n" ) donc, je n'ai pas utilisé ces 2 fonctions (tellg et seekg).

    Voir: http://forums.microsoft.com/MSDN/Sho...08912&SiteID=1
    (Message concernant ce problème.)

    PS:
    Si vous avez des conseilles pour annalyser (parser) un fichier texte, je suis preneur. Mais, je ne pense pas pouvoir les mettre tout de suite en pratique car je souhaite éviter de devoir réécrire la moitié de mon code pour les mettre en pratique.


    PS2:
    S'il vous manque des infos, n'hésitez pas à me l'indiquer.
    Fichiers attachés Fichiers attachés

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Pourrais-tu fournir un exemple minimal réduit, qui compile et qui présente le problème ?

  3. #3
    Nouveau Candidat au Club
    Inscrit en
    Avril 2007
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    Voilà, j'ai ajouté un fichier zip contenant:
    exemple.cpp
    parsersvf.h
    parsersvf.cpp
    flux.tester
    exemple.txt

  4. #4
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    J'utilise unget() plusieurs fois dans une boucle for
    C'est ton bug.

  5. #5
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Pour le coup des unget, je crois (je n'arrive plus à retrouver de références, et ne suis pas spécialiste des iostreams) que la seule garantie est de pouvoir revenir en arrière d'un cran uniquement, et pas plus loin. Il me semble raisonnable qu'une implémentation permette de revenir en arrière de la taille de son buffer interne, et pas plus.

    Pour ce qui est de forcer la lecture totale en mémoire, je ne vois guère que de passer par un stringstream, comme indiqué dans http://c.developpez.com/faq/cpp/?pag...RS_full_buffer

    Pour ce qui est des tellg/seekg, je ne sais pas trop ce que tu entends quand tu dis que les valeurs n'ont aucun sens. La valeur de tellg n'est sensée avoir de sens que pour seekg, et pour personne d'autre.

    Pour ce qui est du parsing, je suis surpris d'un format qui demande parfois à travailler en mode caractères, et parfois en mode ligne. Souvent, c'est l'un ou l'autre. A part ça, si je devais parser un fichier, la méthode employée dépendrait principalement du format de celui-ci. Dans l'ordre :

    • Pour un truc simpliste, genre fichier ini, lecture ligne à ligne, puis analyse de celle-ci à l'aide des fonctions de recherche de chaîne.
    • Pour des fichiers au format que je peux décider moi-même, n'ayant pas besoin d'être écrits à la main, boost::serialisation
    • Pour des fichiers xml, vérifier que c'est vraiment une bonne idée, puis libxml++.
    • Pour des fichiers avec une grammaire intéressante, mais pas trop grosse, boost::spirit (pas encore eu l'occasion de mettre en oeuvre)
    • Pour des fichiers avec une grosse grammaire, de la génération de code à l'aide d'outils comme antlr ou (lex/yacc)/(flex/bison)


    Quelque part dans cette liste, il y aurait aussi un parseur récursif écrit à la mimine, mais je ne sais pas trop où je le placerais...

  6. #6
    Nouveau Candidat au Club
    Inscrit en
    Avril 2007
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par Farks
    J'utilise unget() plusieurs fois dans une boucle for
    Citation Envoyé par Jean-Marc.Bourguet
    C'est ton bug.
    Euh, je ne vois pas en quoi c'est mon bug ?

    Car si tu utilises les fichiers contenu dans le zip et que tu modifies dans le fichier: parser.cpp

    #define NB_LINE_READ 80
    #define NB_PREVIOUS_CHAR 30


    Le programme fonctionne correctement.
    Il lit les 80 premières lignes.
    Affiche la dernière ligne lue.
    Il revient en arrière de 30 caractères.
    Affiche 8 caractères.
    Et affiche la fin de la ligne.


    Tandis qu'avec:
    #define NB_LINE_READ 73
    #define NB_PREVIOUS_CHAR 10

    Le programme n'agit pas correctement.
    Il lit les 73 premières ligne.
    Affiche la dernière ligne lue.
    Il revient en arrière de 10 caractères. => le pointeur se perd
    Affiche 8x le même caractère.
    Et affiche la ligne qu'il avait lu précédemment.

  7. #7
    Nouveau Candidat au Club
    Inscrit en
    Avril 2007
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par JolyLoic
    Pour le coup des unget, je crois (je n'arrive plus à retrouver de références, et ne suis pas spécialiste des iostreams) que la seule garantie est de pouvoir revenir en arrière d'un cran uniquement, et pas plus loin. Il me semble raisonnable qu'une implémentation permette de revenir en arrière de la taille de son buffer interne, et pas plus.
    Ah ok, ça expliquerai mon soucis...
    Dsl Jean-Marc.Bourguet, d'avoir mis en doute ton indication.

    Est-ce que quelqu'un peut m'indiquer la référence expliquant que le unget a un fonctionnement non garanti ?
    Car en utilisant: g++, j'obtiens une application qui fonctionne parfaitement...


    Citation Envoyé par JolyLoic
    Pour ce qui est de forcer la lecture totale en mémoire, je ne vois guère que de passer par un stringstream, comme indiqué dans http://c.developpez.com/faq/cpp/?pag...RS_full_buffer
    Merci pour cette info et pour les explications de comment tu ferais.


    Citation Envoyé par JolyLoic
    Pour ce qui est des tellg/seekg, je ne sais pas trop ce que tu entends quand tu dis que les valeurs n'ont aucun sens. La valeur de tellg n'est sensée avoir de sens que pour seekg, et pour personne d'autre.
    En fait, quand on récupère la valeur de tellg, elle signifie le nombre de caractères depuis le début si on l'utilise sous forme numérique. C'est ce qui permet de savoir le nombre de caractères d'un fichier (C'est possible que ce soit un peu une magouille... Je ne connais pas assez la classe fstream pour garantir ça.).

    Par contre, le bug que j'ai constaté, c'est que je ne reviens pas à la bonne position en utilisant tellg puis seekg.
    Tu peux essayer en utilisant le petit exemple, il y a une partie en commentaire dans le fichier: exemple.cpp qui permet de faire des tests.

    Plus d'info sur ce problème:
    http://forums.microsoft.com/MSDN/Sho...08912&SiteID=1

  8. #8
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par JolyLoic
    Pour le coup des unget, je crois (je n'arrive plus à retrouver de références, et ne suis pas spécialiste des iostreams) que la seule garantie est de pouvoir revenir en arrière d'un cran uniquement, et pas plus loin. Il me semble raisonnable qu'une implémentation permette de revenir en arrière de la taille de son buffer interne, et pas plus.
    Je confirme. (Et je n'ai pas le temps de chercher les references, si j'ai bonne memoire le raisonnement etait assez indirect).

    Pour ce qui est de forcer la lecture totale en mémoire, je ne vois guère que de passer par un stringstream, comme indiqué dans http://c.developpez.com/faq/cpp/?pag...RS_full_buffer
    J'ai ecrit une fois un streambuf qui garantissait le repositionnement n'importe ou.

    Pour ce qui est du parsing, je suis surpris d'un format qui demande parfois à travailler en mode caractères, et parfois en mode ligne. Souvent, c'est l'un ou l'autre. A part ça, si je devais parser un fichier, la méthode employée dépendrait principalement du format de celui-ci. Dans l'ordre :

    • Pour un truc simpliste, genre fichier ini, lecture ligne à ligne, puis analyse de celle-ci à l'aide des fonctions de recherche de chaîne.
    • Pour des fichiers au format que je peux décider moi-même, n'ayant pas besoin d'être écrits à la main, boost::serialisation
    • Pour des fichiers xml, vérifier que c'est vraiment une bonne idée, puis libxml++.
    • Pour des fichiers avec une grammaire intéressante, mais pas trop grosse, boost::spirit (pas encore eu l'occasion de mettre en oeuvre)
    • Pour des fichiers avec une grosse grammaire, de la génération de code à l'aide d'outils comme antlr ou (lex/yacc)/(flex/bison)


    Quelque part dans cette liste, il y aurait aussi un parseur récursif écrit à la mimine, mais je ne sais pas trop où je le placerais...
    Ca permet plus de souplesse. Parmi les avantages:
    - pas necessaire de maitriser un generateur -- donc si on ne connait pas de generateur, c'est bien pour de petite choses
    - on controle mieux les erreurs -- donc pour une grammaire figee, dans un contexte ou donner des messages d'erreurs clairs est important
    - moins de contraintes sur la grammaire -- pour des langages comme le C et le C++, ca evite des hacks pour faire passer la grammaire dans le moule accepte par le generateur;

Discussions similaires

  1. service windows avec Visual Basic 2005 Express
    Par horzy dans le forum VB.NET
    Réponses: 1
    Dernier message: 29/05/2007, 22h58
  2. Compilation avec Visual C++ 2005 Express pour avoir un module python
    Par Freyja dans le forum Déploiement/Installation
    Réponses: 6
    Dernier message: 13/07/2006, 12h12
  3. [Débutant] Linker avec Visual C++ 2005 Express
    Par EL0807 dans le forum VC++ .NET
    Réponses: 2
    Dernier message: 03/04/2006, 16h24
  4. DLL avec Visual C++ 2005 Express
    Par Jloox dans le forum MFC
    Réponses: 5
    Dernier message: 09/03/2006, 18h24

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