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 :

reallocation de memoire


Sujet :

C

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2010
    Messages
    345
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 345
    Points : 539
    Points
    539
    Par défaut reallocation de memoire
    Bonjour,
    Je cherche a lire des tag dans un fichier flac mais ça ne fonctionne pas toujours.
    Je n'arrive pas a voir d'où viens le problème, alors peut être qu'un regard neuf !
    Voici le code que j'utilise
    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "FLAC/all.h"
     
     
    int get_tag_mem(const char* lefile, char* letag)
    {
    		FLAC__StreamMetadata *metadata_block;
    		FLAC__StreamMetadata_VorbisComment *vorbisComment;
    		FLAC__uint32  num_tag;
    		FLAC__StreamMetadata_VorbisComment_Entry *vorbisComment_entry;
    		int ret = -1;
    		size_t lentag = strlen(letag);
            char* buftemp = NULL;
            printf("affichage get_tag_mem\n");
    		if(FLAC__metadata_get_tags(lefile, &metadata_block))
    			{
                    printf("adress letag = %d\n", *letag);
    				vorbisComment = &metadata_block->data.vorbis_comment;
    				for(num_tag = 0; num_tag < vorbisComment->num_comments; num_tag++)	//parcours des tags
    					{
    						vorbisComment_entry = &vorbisComment->comments[num_tag];
    						FLAC__byte *entry = vorbisComment_entry->entry;
    						if(! strncmp((char*)entry, letag, lentag))
                            {
                                buftemp = (char*) realloc(letag, vorbisComment_entry->length + 1);
                                if(buftemp != NULL)
                                {
                                    strcpy(buftemp, (char*) entry);
                                    printf("adress buftemp = %d\n", *buftemp);
                                    printf("adress letag = %d\n", *letag);
                                    letag = buftemp;
                                    printf("adress letag = %d\n", *letag);
                                    printf("letag = %s\n", letag);
                                    ret = strlen(buftemp);
                                }
                                break;
                            }
    					}
    				FLAC__metadata_object_delete(metadata_block);	//liberation de la memoire utilise par libflac
    			}
    		return(ret);
    }
     
     
    int main(int argc, char *argv[])
    {
    	if (argc == 2)
        {
            char *lefile = argv[argc - 1];
            int ret;
            char tag[] = "TITLE=", *buff;
            printf("%s\n", tag);
            buff = (char*) malloc(strlen(tag)+1);
            if(buff != NULL)
            {
                strcpy(buff, tag);
                printf("buff = %s\n", buff);
                ret = get_tag_mem(lefile, buff);
                printf("affichage dans main\n");
                printf("retour = %d\n", ret);
                printf("buff = %s\n", buff);
                printf("adress letag = %d\n", *buff);
                free(buff);
            }
        }
        return 0;
    Et voici la sortie écran
    alain@debian:~/Documents/Language_C/testrealloc/lib$ ./testrealloc 02\ Love\ Is\ Blind.flac
    TITLE=
    buff = TITLE=
    affichage get_tag_mem
    adress letag = 84
    adress buftemp = 84
    adress letag = 84
    adress letag = 84
    letag = TITLE=Love Is Blind
    affichage dans main
    retour = 19
    buff = TITLE=Love Is Blind
    adress letag = 84
    alain@debian:~/Documents/Language_C/testrealloc/lib$ ./testrealloc 01\ Element\ Of\ Freedom\ \(Intro\).flac
    TITLE=
    buff = TITLE=
    affichage get_tag_mem
    adress letag = 84
    adress buftemp = 84
    adress letag = 48
    adress letag = 84
    letag = TITLE=Element Of Freedom (Intro)
    affichage dans main
    retour = 32
    buff = 0��
    adress letag = 48
    alain@debian:~/Documents/Language_C/testrealloc/lib$
    Si quelqu'un vois quelquechose qui m'échappe.
    Merci.
    ctac_

  2. #2
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Ligne 33 : tu affectes une valeur à ton paramètre letag mais il est passé par valeur, tu ne risques pas de le récupérer. D'ailleurs avoir un paramètre de fonction qui sert à la fois pour l'entrée et la sortie c'est vraiment bof, ça se justifie rarement. À ta place je modifierais la signature de la fonction en quelque chose du style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int get_tag_mem(char *buf, size_t bufsize, const char *filename, const char *tagname);
    Ou encore, si tu tiens à ce que la fonction s'occupe de l'allocation du buffer de destination (mais sans code d'erreur, sauf à ajouter un paramètre int * ou une variable globale) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *get_tag_mem(const char *filename, const char *tagname);

    D'autre part, ce genre de chose : printf("adress letag = %d\n", *letag);, à l'exécution ça ne fonctionne pas (et c'est même comportement indéfini si le buffer fait moins de sizeof(int)). Pour afficher une adresse mémoire on utilise le format "%p" sans déréférencer le pointeur, comme ceci : printf("adresse de 'letag' : %p\n", letag);.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2010
    Messages
    345
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 345
    Points : 539
    Points
    539
    Par défaut
    Ok, merci.
    Le problème venait du passage par valeur (erreur de débutant).
    Par contre, c'est vraiment bof ??
    Ta proposition rajoute 2 paramètres qui nécessite de connaitre la taille de ce que je veux récupérer ou de prévoir un buffer assez grand.
    Pour le code d'erreur, le retour en int du nombre de char permet de renvoyer un nombre négatif
    Merci pour le %p, c'est mieux.
    Cordialement,
    ctac

  4. #4
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Citation Envoyé par ctac_ Voir le message
    Ta proposition rajoute 2 paramètres
    Oui, et donc ? La taille de ta pile n'est pas limitée à 16 octets, profites-en !


    Citation Envoyé par ctac_ Voir le message
    qui nécessite de connaitre la taille de ce que je veux récupérer ou de prévoir un buffer assez grand.
    En fait dans l'idée bufsize, la taille du buffer, est un paramètre de sécurité à la manière de strncpy, snprintf, etc...

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2010
    Messages
    345
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 345
    Points : 539
    Points
    539
    Par défaut
    Citation Envoyé par Matt_Houston Voir le message
    Oui, et donc ? La taille de ta pile n'est pas limitée à 16 octets, profites-en !
    Oui, c'est vrai mais, certain tag comme "cuesheet" peuvent contenir disons 1000 caractères en utf8 et j'imagine que libflac se sert aussi de la pile.
    L'idée d'avoir 1 seul paramètre, utilisé en entrée sortie et redimentionné à ma convenance me plait assez.
    S'il y a contre-indication, je veux bien lire de la doc sur le sujet.

    Citation Envoyé par Matt_Houston Voir le message
    En fait dans l'idée bufsize, la taille du buffer, est un paramètre de sécurité à la manière de strncpy, snprintf, etc...
    Là, par contre, je ne comprend pas trop.
    Je ne vois pas de paramètre additionnel dans strncpy et snprintf.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int snprintf(char *str, size_t size, const char *format, ...)
    snprintf retourne -1 en cas d'erreur et size ou plus si str est trop petit.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *strncpy(char *dest, const char *src, size_t n)
    Ici, aucune protection, si n est plus grand que "dest"

    Cordialement,
    ctac

  6. #6
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Citation Envoyé par ctac_ Voir le message
    Oui, c'est vrai mais, certain tag comme "cuesheet" peuvent contenir disons 1000 caractères en utf8 et j'imagine que libflac se sert aussi de la pile.
    La chaîne pourrait bien peser 18 gigas, seul le pointeur est sur la pile. D'autre part as-tu lu le code de libflac pour supposer cela ? À moins de coder pour un système embarqué (et encore) tu n'as pas à te préoccuper d'un dépassement de pile. Premature optimization is the root of all evil.


    Citation Envoyé par ctac_ Voir le message
    L'idée d'avoir 1 seul paramètre, utilisé en entrée sortie et redimentionné à ma convenance me plait assez.
    S'il y a contre-indication, je veux bien lire de la doc sur le sujet.
    La contre-indication c'est surtout le manque de clarté qui vient du fait que sémantiquement tu donnes plusieurs significations à un même paramètre. D'autre part, que se passe-t-il si l'utilisateur décide de se servir de ta fonction comme ceci : get_tag_mem(lefile, "TITLE=") ? Mieux vaut que la doc soit claire !


    Citation Envoyé par ctac_ Voir le message
    Là, par contre, je ne comprend pas trop.
    Je ne vois pas de paramètre additionnel dans strncpy et snprintf.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int snprintf(char *str, size_t size, const char *format, ...)
    snprintf retourne -1 en cas d'erreur et size ou plus si str est trop petit.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *strncpy(char *dest, const char *src, size_t n)
    Tu ne vois pas de différence entre le fait que la fonction connaisse ou pas la taille du buffer de destination ?

    Citation Envoyé par ctac_ Voir le message
    Ici, aucune protection, si n est plus grand que "dest"
    Donc la règle c'est de conduire à droite et l'automobiliste, qui le sait, roule sur la voie de gauche.. que veux-tu que je te dise ? La responsabilité incombe à celui qui fournit les données : le code appelant.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. realloc: mise à jour d'adresse memoire
    Par twity dans le forum C
    Réponses: 20
    Dernier message: 17/11/2012, 20h12
  2. [Debutant]reallocation de memoire d'un tableau de type perso
    Par killerjeff dans le forum Débuter
    Réponses: 3
    Dernier message: 04/08/2004, 17h09
  3. gestionnaire de memoire
    Par elone dans le forum C
    Réponses: 2
    Dernier message: 23/01/2003, 00h31
  4. récupérer la memoire et tableau dynamique
    Par Guigui_ dans le forum Langage
    Réponses: 6
    Dernier message: 06/01/2003, 08h02
  5. Réponses: 4
    Dernier message: 03/12/2002, 16h47

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