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 :

Fuite de memoire avec strdup


Sujet :

C

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2013
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 11
    Points : 17
    Points
    17
    Par défaut Fuite de memoire avec strdup
    Bonjour

    J'asseye de faire un programme qui lit un fichier texte et qui met les mots dans une liste simplement chaînée. Un mot par noeud.

    En surface mon programme fonctionne correctement, seulement lorsque j'utilise valgrind pour verifier les fuites de mémoire, je m'aperçoit que je ne gère pas ma memoire convenablement.

    En gros, je pene que strdup créé dynamiquement un pointeur vers une chaine de caractères pour chaque mot. Donc si mon fichier texte à 40 mots, il va y avoir 40 zones mémoires dynamiques que je dois effacer.

    J'ai asseye de mettre le contenu du strdup dans un char * par exemple, et de faire free() sur cela à différents endroits. Résultat soit que j'ai une fuite de mémoire, soit que j'efface le pointeur trop top et il manque des mots dans ma liste.

    Comment puis-je éviter les fuites avec strdup ?

    Merci!

    Mon main :
    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
     
     
    int main(int argc, char **argv)
    {
        llist ma_liste = NULL;
        char tampon_mot[100];
     
        FILE *file = fopen("fichier.txt", "r");
     
        if(file == NULL) {
          printf("erreur ouverture de fichier\n");
          return 1;
        }
     
        while(fscanf(file, "%s", tampon_mot) == 1){
          ma_liste = ajouterEnTete(ma_liste, strdup(tampon_mot));
        }
        fclose(file);
        afficher_liste(ma_liste);
        effacerListe(ma_liste);
     
        return 0;
    }
    Ma structure pour ma liste chainée :

    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
     
     
    typedef struct element element;
    struct element
    {
        char * val;
        struct element *nxt;
    };
     
    typedef element* llist;
     
    llist ajouterEnTete(llist liste, char * valeur)
    {
        element* nouvelElement = malloc(sizeof(element));
        nouvelElement->val = valeur;
        nouvelElement->nxt = liste;
        return nouvelElement;
    }
     
    void afficherListe(llist liste)
    {
        element *tmp = liste;
        while(tmp != NULL)
        {
            printf("%s ", tmp->val);
            tmp = tmp->nxt;
        }
        printf("\n");
    }
     
    llist effacerListe(llist liste)
    {
        if(liste == NULL)
        {
            return NULL;
        }
        else
        {
            element *tmp;
            tmp = liste->nxt;
            free(liste);
            return effacerListe(tmp);
        }
    }

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Il manque la procédure la plus importante, celle pour supprimer un element, mais il n'y a rien de compliqué
    À chaque suppression d'un element, il faut libérer la valeur.

    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
    void clearListe(llist* liste) {
        if (liste == NULL) { return; }
     
        element* tmp = (*liste);
        element* next;
     
        while(tmp != NULL) {
            if (tmp->val != NULL) {
                free(tmp->val);
    //          tmp->val = NULL;
            }
     
            next = tmp->nxt;
     
            free(tmp);
     
            tmp = next;
        }
     
        (*liste) = NULL;
    }
    PS: N'oublie pas de tester si tmp->val est NULL avant de faire quelque chose.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2013
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 11
    Points : 17
    Points
    17
    Par défaut
    Merci pour le tuyeau, à vrai dire j'avais oublié d'inclure le code plus haut. Voici ce que j'avais déjà.

    À premiere vue, cela fonctionne mais valgrind m'indique encore une fuite de mémoire pour le strdup du main.

    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
     
    llist effacerListe(llist liste)
    {
        if(liste == NULL)
        {
            return NULL;
        }
        else
        {
            element *tmp;
            tmp = liste->nxt;
            free(liste);
            return effacerListe(tmp);
        }
    }
    Citation Envoyé par foetus Voir le message
    Il manque la procédure la plus importante, celle pour supprimer un element, mais il n'y a rien de compliqué
    À chaque suppression d'un element, il faut libérer la valeur.

    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
    void clearListe(llist* liste) {
        if (liste == NULL) { return; }
     
        element* tmp = (*liste);
        element* next;
     
        while(tmp != NULL) {
            if (tmp->val != NULL) {
                free(tmp->val);
    //          tmp->val = NULL;
            }
     
            next = tmp->nxt;
     
            free(tmp);
     
            tmp = next;
        }
     
        (*liste) = NULL;
    }
    PS: N'oublie pas de tester si tmp->val est NULL avant de faire quelque chose.
    Ahhhh ! Je comprends, je liberais mes noeuds, mais pas le contenu des noeuds !

    Merci beaucoup !

  4. #4
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    En gros, je pene que strdup créé dynamiquement un pointeur vers une chaine de caractères pour chaque mot. Donc si mon fichier texte à 40 mots, il va y avoir 40 zones mémoires dynamiques que je dois effacer.
    Toi, tu es presque devin ! Ou alors tu as lu le manuel
    Citation Envoyé par http://manpagesfr.free.fr/man/man3/strdup.3.html
    La fonction strdup() renvoie un pointeur sur une nouvelle chaîne de caractères qui est dupliquée depuis s. La mémoire occupée par cette nouvelle chaîne est obtenue en appelant malloc(3), et peut (doit) donc être libérée avec free(3).
    Ahhhh ! Je comprends, je liberais mes noeuds, mais pas le contenu des noeuds !
    La règle d'or est : un malloc = un free. Le corollaire doré : une boucle de malloc = une boucle de free. T'inquiète, on s'est déjà tous fait avoir.

  5. #5
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 860
    Points : 219 062
    Points
    219 062
    Billets dans le blog
    120
    Par défaut
    Bonjour,

    C'est surtout que strdup est un peu une fonction piège : elle alloue de la mémoire (sans avoir de nom comme alloc/init). Il faut lire la documentation pour être certain qu'elle alloue de la mémoire (contrairement à beaucoup d'autres fonctions qui laisse cela pour l'utilisateur/ou encore, qui gère la mémoire en interne sans rien demander à l'utilisateur).
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

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

Discussions similaires

  1. fuite memoire avec les termcaps
    Par m0ul3sh0t dans le forum C
    Réponses: 3
    Dernier message: 06/03/2008, 13h29
  2. fuite memoire avec sfml
    Par themulot dans le forum SFML
    Réponses: 2
    Dernier message: 27/11/2007, 10h25
  3. Outils pour rechercher des fuites de memoires dans un prog
    Par elekis dans le forum Applications et environnements graphiques
    Réponses: 5
    Dernier message: 29/04/2005, 21h06
  4. fuite de memoire dans une liste de pointeur sur composant
    Par Nicolos_A dans le forum Composants VCL
    Réponses: 2
    Dernier message: 16/12/2004, 08h46
  5. correction de fuite de memoire
    Par vince3320 dans le forum C
    Réponses: 38
    Dernier message: 28/06/2004, 11h27

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