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 :

lecture binaire sur un flux


Sujet :

C++

  1. #1
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut lecture binaire sur un flux
    Salut à tous.
    Voila, je dois faire des lectures binaires sur un flux de la stl. Pour cela, je commence par l'ouvrir en binaire puis j'utilise une fonction pour lire les données au fur et à mesure. J'ai mis au point deux versions de cette fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    	int yaread(struct SDL_RWops *context, void *ptr, int size, int maxnum) {
    		std::istream* s = (std::istream*)context->hidden.unknown.data1;
    		int taille=0;
    		while(!s->eof() && taille<size*maxnum) {
    			((char*)ptr)[taille] = s->get();
    			taille++;
    		}
    		return taille/size;
    	}
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    	int yaread(struct SDL_RWops *context, void *ptr, int size, int maxnum) {
    		std::istream* s = (std::istream*)context->hidden.unknown.data1;
    		int beg = s->tellg();
    		s->seekg(0,ios::end);
    		int end = s->tellg();
    		s->seekg(beg,ios::beg);
    		int taille = size*maxnum<=end-beg?size*maxnum:end-beg;
    		s->read((char*)ptr,taille);
    		return taille/size;
    	}
    Ne vous préoccupez pas trop des deux premières lignes ni de la valeur de retour, cette fonction est appellée par une bibliothèque qui n'est pas de moi.
    Il faut savoir que ces deux versions fonctionnent, j'arrive à charger correctement mon image (parceque c'est une image) et à l'afficher. Ensuite, l'objet contenant cette fonction est détruit, le flux est fermé et mon programme continue son exécution (c'est un jeu de société, ca peut prendre longtemps).
    Le problème est que si j'utilise la version numéro 2 de cette fonction, le destructeur du flux provoque un plantage en accédant à une portion de mémoire invalide (je rapelle que ce destructeur est appelé longtemps après l'exécution de ma fonction.
    Je pourrais bien sur n'utiliser que la première version de cette fonction, mais elle est incroyablement lente (forcément, si on lit les octets un à un...).

    Quelqu'un verrait-il ou est l'erreur? J'utilise visual studio 2005.

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Le stream est bien en binaire? Je ne sais plus trop sur quelle plate-forme ou avec quelle version, mais il me semble que certaines classes de stream ont des problèmes avec seekg()/tellg() quand elles sont ouvertes en mode texte...

    Et aussi, je ne suis pas certain de la priorité du ?: et du >=, tu devrais peut-être t'en assurer avec des parenthèses...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    Non non, rien à voir avec ca.
    Je dis bien que ces deux implémentations fonctionnent parfaitement. D'ailleurs la portion de code servant à vérifier si je ne suis pas arrivé à la fin de mon fichier ne sert quasiment à rien puisque je peux constater avec un peu de logging que la bibliothèque appelant ces fonctions ne demande jamais plus que la taille du fichier (c'est une biblio de lecture de JPG, je suppose qu'il est marqué quelquepart au début du fichier la taille qu'il fait).
    Le seul problème est que la seconde implémentation semble "déteriorer" le flux. Ce qui fait qu'à sa destruction (qui se produit longtemps après sa fermeture) son destructeur va causer un plantage.

    Edit: ca vient justement de me donner une petite idée. J'ai viré cette fameuse partie du code et visiblement le résultat est exactement le même. On dirait que c'est la fonction read() qui pose problème.

  4. #4
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    Ca va, je crois avoir trouvé une solution. Ma

  5. #5
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    Ca va, je crois avoir trouvé une solution. Ma fonction est devenue:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    	int yaread(struct SDL_RWops *context, void *ptr, int size, int maxnum) {
    		std::istream* s = (std::istream*)context->hidden.unknown.data1;
     
    		return s->rdbuf()->sgetn((char*)ptr,size*maxnum)/size;
    	}
    En plus, contrairement à istream.read() je recois directement le nombre de bytes lus. Par contre il me semble que j'avais déja eu des problèmes avec certaines implémentations de la stl qui ne permettaient pas de récupérer un pointeur le buffer. Enfin, je verrais bien quand je testerais sous gcc.

  6. #6
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    Et m***, ca cesse de fonctionner dés que je compile en mode release. Je commence à en vouloir à visual studio la

  7. #7
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 292
    Par défaut
    Plus simple que ton dernier truc, tu as std::istream::readsome(), non ?
    Je suis sceptique sur ta première fonction, à cause du eof qui intervient avant le get(), soit trop tard.

    Sinon, il n'y a pas de problèmes de mélanges de reinterpret_cast alors que tu es en plein héritage, possiblement multiple (si std::fstream, sans o ni i) ? Utilises-tu la bonne vtable ? -> si tu affiches la valeur du pointeur sur std::istream avant et après obsfuscation via un void* (si je comprends bien).

    Evidemment, il faut s'assurer que le type du pointeur officiellement stocké soit réutilisé avant utilisation, et pas un autre.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  8. #8
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    Citation Envoyé par Luc Hermitte
    Plus simple que ton dernier truc, tu as std::istream::readsome(), non ?
    Je suis sceptique sur ta première fonction, à cause du eof qui intervient avant le get(), soit trop tard.

    Sinon, il n'y a pas de problèmes de mélanges de reinterpret_cast alors que tu es en plein héritage, possiblement multiple (si std::fstream, sans o ni i) ? Utilises-tu la bonne vtable ? -> si tu affiches la valeur du pointeur sur std::istream avant et après obsfuscation via un void* (si je comprends bien).

    Evidemment, il faut s'assurer que le type du pointeur officiellement stocké soit réutilisé avant utilisation, et pas un autre.
    Ecoute, c'est une fonction permettant de faire communiquer le système de flux de la stl avec le système de flux utilisé par SDL (oui oui, la bibliothèque C). Pour le moment je laisse un peu de coté la pure beauté du code. Pour ce qui est de la première fonction, comme je le disais je ne peux me résoudre à l'utiliser car elle est beaucoup trop lente.
    J'essaie surtout de faire en sorte que ca fonctionne, les détails c'est après.
    Le readsome ne fonctionne pas, il est concu pour ne lire que les bytes contenus dans le buffer, sans accès au média.
    Néanmoins, pour le casting, il n'y a normalement pas de problème à utiliser un fstream ou ifstream en le castant en istream je pense, vu que tous appelent les méthodes du buffer qui elles sont virtuelles. Dites le moi si je me trompe.

  9. #9
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    Bon ben, en fait j'ai fini par me rendre compte que tel que j'essaie de concevoir mon truc ca semble incapable de fonctionner. J'ai fini par trouver une autre façon de faire qui devrait surcharger un peu plus la mémoire mais qui logiquement ne posera pas autant de problème.

    Note à moi même: ne plus essayer de faire exécuter du code C++ par une bibliothèque en C

  10. #10
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 292
    Par défaut
    Il peut y avoir des problèmes avec les castings brutaux. Typiquement dès qu'il des héritages multiples à l'oeuvre.
    Suivant les compilos, qui implèmentent les vtables à des sauces différentes, tu vas avoir des écarts sur les valeurs des pointeurs sur un même objet selon que tu considères le pointeur de type ClasseMere*, ou un pointeur vers une quelconque classe fille.

    Bon maintenant, j'avoue que je n'ai plus en tête le diagramme de classe des classes de flux de la SL, ni le contenu du bouquin de Lippman sur le modèle objet du C++ (un peu la référence dans le domaine).
    D'où que je t'invitais à afficher la valeur brute de ton pointeur avant et après les 15000 transtypages. Si tu as bien des écarts, alors attention à réaliser tes reinterpret_cast<> de façon bijective avant de jouer avec les cast implicites vers les types parents.
    Je ne garantis pas que cela vienne de là. C'est juste un peu la seule piste à laquelle je songe.

    Ceci dit. Pop. Une autre piste me vient à l'esprit. Si tu as des classes templates, en particulier celles de la SL, compilées d'une certaine manière dans une bibliothèque (statique ou dynamique), et que tu passes un pointeur vers un de ces types à un autre binaire (bibliothèque ou exécutable), il faut s'assurer que compilo et options de compilation sont bien identiques entre les deux binaires. Particulièrement sous windows.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

Discussions similaires

  1. flux binaires sur RS232
    Par Tymk dans le forum C++
    Réponses: 8
    Dernier message: 13/07/2008, 01h17
  2. lecture & ecriture sur le port serie
    Par anouar dans le forum Entrée/Sortie
    Réponses: 3
    Dernier message: 08/07/2005, 17h15
  3. Lecture / écriture sur un port com
    Par dorian833 dans le forum C++
    Réponses: 7
    Dernier message: 07/07/2005, 15h20
  4. [Stratégie] Lecture ponctuelle d'un flux continu
    Par christopheJ dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 30/07/2004, 16h30
  5. [Servlet][Deb]envoyer image gif sur le flux http
    Par ptitBoutchou dans le forum Servlets/JSP
    Réponses: 15
    Dernier message: 09/04/2004, 10h12

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