Soutenez-nous
Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 10 sur 10
  1. #1
    Nouveau Membre du Club
    Inscrit en
    janvier 2008
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : janvier 2008
    Messages : 39
    Points : 37
    Points
    37

    Par défaut Buffer E/S rapide pour fichier

    Bonjour !

    Dans certaines applications qui doivent charger, interpréter, écrire des fichiers, les opérations de lecture/écriture prennent parfois beaucoup de temps si on écrit caractère par caractère par exemple.
    J'ai donc progammé une bibliothèque de fonctions de lecture/écriture dans des fichiers, avec un buffer. Par exemple dans le cas de l'importation d'un fichier WAV avec traitement et écriture à la volée, j'ai diminué le temps d'exécution par 4.

    Je donne les sources ici, c'est une archive 7-zip.

    Je me demande quand même si ce que j'ai fait n'existe pas déjà dans des librairies +/- standard, c'est quand même pratique.

    J'ai créé 2 structures de données, une pour le buffer en lecture et une pour le buffer en écriture. Principalement parce que c'est beaucoup plus facile comme ça plutôt que de faire un unique type de buffer qui fonctionnerait en lecture et en écriture, et qui aussi consommerait un peu plus de CPU. Enfin ça viendra peut-être, mais pour l'instant moi je n'en ai pas besoin...

    Les fonctions disponibles sont :
    - écriture/lecture d'un unique caractère
    - écriture/lecture d'une plage entière
    - positionnement à un endroit particulier dans le fichier
    - récupérer la position courante

  2. #2
    Responsable Modération
    Avatar de diogene
    Homme Profil pro Patrick Gonord
    Enseignant Chercheur
    Inscrit en
    juin 2005
    Messages
    5 665
    Détails du profil
    Informations personnelles :
    Nom : Homme Patrick Gonord
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : juin 2005
    Messages : 5 665
    Points : 13 781
    Points
    13 781

    Par défaut

    Quelques remarques (en commentaires) après une lecture rapide :

    Code :
    1
    2
    3
    4
    5
    6
    filebufw *filebuf_openw(char *nom, int param, int size) {
    	filebufw *fb;
    	if((fb=malloc(sizeof(*fb))) == NULL) return NULL;
    	fb->file = fopen(nom, (param ? "wb+":"wb"));
    	if(fb->file == NULL) return NULL;           // perte mémoire
    ....
    idem dans filebufr *filebuf_openr(char *nom, int size)

    Code :
    1
    2
    3
    int filebuf_addm(void *ptr, int size, filebufw *fb) {
    ....
    	ptr+=towrite; ....                         //ptr est void *
    idem dans filebuf_popm(void *ptr, int size, filebufr *fb)

  3. #3
    Nouveau Membre du Club
    Inscrit en
    janvier 2008
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : janvier 2008
    Messages : 39
    Points : 37
    Points
    37

    Par défaut

    Bonjour !

    En effet diogene, je m'étais aperçu de la perte de mémoire mais je n'avais pas internet pendant ces vacances alors je n'ai pas encore actualisé le code. Je crois bien que j'ai aussi fait une ou deux retouches plus esthétiques qu'autre chose, en tout cas ce sera dans le nouveau code. Je préviendrai quand il sera disponible.

    Remplacer
    Code :
    	if(fb->file == NULL) return NULL;           // perte mémoire
    par
    Code :
    	if(fb->file == NULL) {free(fb); return NULL;}
    Mais pour le void* moi j'aime bien parce que ça évite les warnings du compilateur. Je veux dire, la fonction n'est pas faite pour écrire des char* uniquement, mais n'importe quelle donnée.

    Si on veut écrire des données int ou double ou n'importe quelle structure exotique on met tranquilement :
    Code :
    filebuf_addm(&ma_donnee, sizeof(ma_donnee), fb)
    et le tour est joué...

  4. #4
    Responsable Modération
    Avatar de diogene
    Homme Profil pro Patrick Gonord
    Enseignant Chercheur
    Inscrit en
    juin 2005
    Messages
    5 665
    Détails du profil
    Informations personnelles :
    Nom : Homme Patrick Gonord
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : juin 2005
    Messages : 5 665
    Points : 13 781
    Points
    13 781

    Par défaut

    Le passage d'un void * en paramètre est logique. C'est l'incrément du void *,qui me gène :
    Du fait que le type (donc la taille) de l'objet pointé est inconnu, de combien sera incrémenté ptr ? En bonne logique, ce devrait être interdit.
    J'ai testé sur 2 compilateurs. Le premier me donne une erreur et le second un warning (ce qui est le moins qu'on puisse attendre).
    Je n'ai pas trouvé de comportement clairement défini dans la norme sur la question de l'arithmétique mettant en cause un pointeur sur void.

    Pour ces raisons, j'éviterais ce genre d'écriture.

  5. #5
    Nouveau Membre du Club
    Inscrit en
    janvier 2008
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : janvier 2008
    Messages : 39
    Points : 37
    Points
    37

    Par défaut

    J'ai actualisé les sources avec les modifications que j'ai indiquées dans mon dernier post.
    Je donne les sources ici, c'est une archive 7-zip.

    Pourtant, je n'ai aucune erreur ni aucun warning de compilation (avec mingw sous windows) alors je ne me suis pas préoccupé du tout de la manipulation du void*. Peux-tu indiquer les compilateurs que tu as utilisé ?

    En tout cas si on fait comme ça le problème doit être réglé :
    Code :
    ptr=(char*)ptr+towrite;
    Je vais me documenter un peu avant de faire la modif dans le code. En tout cas il y a plusieurs endroits à modifier.

    Mais quand même, vu que l'unité élémentaire de mémoire c'est l'octet, mon void* pointe vers un certain octet, alors en incrémentant de N on va aller N octets plus loin... et comme sizeof() renvoie un nombre d'octets, tout le monde doit être content ! en fait je ne vois pas trop comment il faut se représenter ce fameux void* si tu dis que ça pose problème... pour moi c'est de le transtyper en char* qui n'est pas logique parce que la nature des données manipulées on s'en moque pas mal.

    Est-ce que tu peux expliquer ? et dire dire ce qui ne va pas dans mon avis ?

  6. #6
    Responsable Modération
    Avatar de diogene
    Homme Profil pro Patrick Gonord
    Enseignant Chercheur
    Inscrit en
    juin 2005
    Messages
    5 665
    Détails du profil
    Informations personnelles :
    Nom : Homme Patrick Gonord
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : juin 2005
    Messages : 5 665
    Points : 13 781
    Points
    13 781

    Par défaut

    Un compilateur Borland (Builder 6) indiquait une erreur. Mingw émettait un warning. Ca doit dépendre des options de warnings à la compilation si le tien était muet sur le sujet.
    Pour info, l'unité de mémoire est le byte (qui correspond souvent à un octet).

    La norme dit
    A pointer to void shall have the same representation and alignment requirements as a pointer to a character type
    Mais elle ne dit pas (ou du moins je ne sais pas où) que l'arithmétique des void* est celle des char*.

    Normalement, incrémenter un pointeur augmente l'adresse concernée du nombre de bytes égal à la taille de l'objet pointé. Dans le cas de void *, cette taille est inconnue et on ne devrait pas faire d'arithmétique sur ces pointeurs (ni les déréférencer). C'est leur différence par rapport à un char*.

    A ta place, j'opérerais un transtypage tant que ce point est incertain.

  7. #7
    Nouveau Membre du Club
    Inscrit en
    janvier 2008
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : janvier 2008
    Messages : 39
    Points : 37
    Points
    37

    Par défaut

    Aah bah si c'est la norme qui le dit
    J'ai mis à jour le code, toujours dispo ici en archive 7-zip.

    Mais quand je compile j'active TOUS les warnings pourtant (-Wall), sous MingW et rien n'apparaît à ce sujet. J'ai une version plutôt récente de MingW, celle incluse dans CodeBlocks 8.02

  8. #8
    Rédacteur/Modérateur
    Avatar de Melem
    Homme Profil pro Jessee Michaël Christian Edouard
    Ingénieur développement logiciels
    Inscrit en
    janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Nom : Homme Jessee Michaël Christian Edouard
    Âge : 28
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : janvier 2006
    Messages : 3 656
    Points : 8 375
    Points
    8 375

    Par défaut

    Citation Envoyé par komput Voir le message
    J'ai une version plutôt récente de MingW, celle incluse dans CodeBlocks 8.02
    Et qui est la même que celle incluse depuis C:B 1.0 .

  9. #9
    Membre expérimenté Avatar de dapounet
    Profil pro
    Étudiant
    Inscrit en
    juillet 2007
    Messages
    472
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : juillet 2007
    Messages : 472
    Points : 557
    Points
    557

    Par défaut

    Citation Envoyé par komput Voir le message
    Je me demande quand même si ce que j'ai fait n'existe pas déjà dans des librairies +/- standard, c'est quand même pratique.
    Il y a les fonctions setbuf() et setvbuf().
    :wq

  10. #10
    Nouveau Membre du Club
    Inscrit en
    janvier 2008
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : janvier 2008
    Messages : 39
    Points : 37
    Points
    37

    Par défaut

    Et qui est la même que celle incluse depuis C:B 1.0 .
    moi qui pensais qu'ils suivaient un minimum, je vais regarder ça

    Il y a les fonctions setbuf() et setvbuf().
    Oui, mais j'ai fait l'essai sur ma machine et ça marche pas. Je veux dire mon petit code est toujours 2-3 fois plus rapide quand j'écris caractère par caractère. Je ne l'ai toujours pas testé sous linux, ma machine a trop de mal. Mais si vous avez des chiffres, c'est toujours bienvenu...

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •