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 :

Plusieurs malloc : quid de free ?


Sujet :

C

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 56
    Points : 35
    Points
    35
    Par défaut Plusieurs malloc : quid de free ?
    Bonjour à tous,
    Dans mon programme flex-bison, je fais un malloc sur une variable globale à chaque fois qu'une expression est reconnu, c'est à dire en quelques sortes j'ai ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    variable globale :
    char* s;
     
    fonction fct :
    if(Condition){
      s = malloc(20*sizeof(char));
      /* traitement */
    }
     
    main :
    fct();
    free(s);
    Evidement je ne peux passé s en paramètre a la fonction fct, car celle ci est fictive pour illustrer l'exemple, je rappelle que c'est un programme flex-bison.
    J'aurais voulu savoir si le seul free de s malgré plusieurs malloc sur s était suffisant ou bien s'il y avait des fuites de mémoire.

    Merci de votre aide.

  2. #2
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 211
    Points
    23 211
    Par défaut
    Bonjour,

    Il y aura en effet une fuite de mémoire.
    Il faut faire un free par malloc.

  3. #3
    Expert éminent
    Avatar de transgohan
    Homme Profil pro
    Développeur Temps réel Embarqué
    Inscrit en
    Janvier 2011
    Messages
    3 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Temps réel Embarqué

    Informations forums :
    Inscription : Janvier 2011
    Messages : 3 146
    Points : 9 386
    Points
    9 386
    Par défaut
    Le mieux serait d'initialiser le pointeur.
    Puis avant le malloc vérifier que le pointeur ne cible pas une zone mémoire.
    Si tel est le cas on utilise free avant de faire un nouveau malloc.

    « Toujours se souvenir que la majorité des ennuis viennent de l'espace occupé entre la chaise et l'écran de l'ordinateur. »
    « Le watchdog aboie, les tests passent »

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 56
    Points : 35
    Points
    35
    Par défaut
    Tout d'abord merci de vos réponses.
    Le problème c'est que si je fais un free avant de refaire un autre malloc, mon programme ne marche plus.
    J'aimerais faire un free global en fin de programme mais ça ne marche pas.
    Par exemple la taille de s = sizeof(s) / sizeof(char);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for(i=0;i<sizeof(s) / sizeof(char);i++){
      free(s+i);
    }
    Là je désalloue de la mémoire déja désalloué.

    Le problème vient du fait que s n'est pas une matrice. Donc comment faire plusieurs free ?

  5. #5
    Expert éminent
    Avatar de transgohan
    Homme Profil pro
    Développeur Temps réel Embarqué
    Inscrit en
    Janvier 2011
    Messages
    3 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Temps réel Embarqué

    Informations forums :
    Inscription : Janvier 2011
    Messages : 3 146
    Points : 9 386
    Points
    9 386
    Par défaut
    Malheureux on ne désaloue pas un char. Tu tentes de faire un truc du genre :
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char s = 'a';
    free(s);
    Ce qui est différent de :
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char *s;
    s = (char*) malloc (2 * sizeof(char) );
    s[0] = 'a';
    s[1] = '\0';
    free(s);

    Le problème c'est que si je fais un free avant de refaire un autre malloc, mon programme ne marche plus.
    As-tu vérifié que tu ne tentais pas de désalouer du vide ?
    Ceci fonctionne à merveille :
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char *s;
    s = (char*) malloc (2 * sizeof(char) );
    free(s);
    s = (char*) malloc (5 * sizeof(char) );
    free(s);

    « Toujours se souvenir que la majorité des ennuis viennent de l'espace occupé entre la chaise et l'écran de l'ordinateur. »
    « Le watchdog aboie, les tests passent »

  6. #6
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    Citation Envoyé par Fer2Lance
    Le problème c'est que si je fais un free avant de refaire un autre malloc, mon programme ne marche plus.
    Là, ça cache un autre problème qu'on ne peut pas détecter avec le code succint fourni mais il y a, assurément, une grosse cagade quelque part ailleurs !

    Citation Envoyé par transgohan
    Le mieux serait d'initialiser le pointeur.
    Puis avant le malloc vérifier que le pointeur ne cible pas une zone mémoire.
    Si tel est le cas on utilise free avant de faire un nouveau malloc.
    Oui mais ... non. Si, techniquement, ça tient parfaitement la route et c'est tout à fait juste, en procédant de la sorte, le code n'a plus/pas beaucoup de sens (quoique ... ça n'arrête pas toujours tout le monde !) : les allocations sont toujours de la même taille, on manipule toujours la même variable pointeur (s) et donc ça reviendrait à :

    • initialiser s à NULL au tout début
    • désallouer s (s'il n'est pas NULL)
    • "perdre" son contenu
    • ré-allouer s, à la même taille
    • changer son contenu


    Pourquoi faire simple quand ...

    Je pense qu'il nous manque des éléments pour qu'on puisse t'aider efficacement.
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  7. #7
    Expert éminent
    Avatar de transgohan
    Homme Profil pro
    Développeur Temps réel Embarqué
    Inscrit en
    Janvier 2011
    Messages
    3 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Temps réel Embarqué

    Informations forums :
    Inscription : Janvier 2011
    Messages : 3 146
    Points : 9 386
    Points
    9 386
    Par défaut
    En effet si la taille reste toujours la même il vaut mieux allouer en début de programme, jouer du strcpy pour vider la chaîne puis faire un free à la fin.
    Mais comme dit sans plus de détails on ne peut pas vraiment sortir LA solution sans penser à toutes les solutions possibles (sans compter les possibles approximations de code que tu nous donne).

    « Toujours se souvenir que la majorité des ennuis viennent de l'espace occupé entre la chaise et l'écran de l'ordinateur. »
    « Le watchdog aboie, les tests passent »

  8. #8
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 56
    Points : 35
    Points
    35
    Par défaut
    Citation Envoyé par transgohan Voir le message
    Ceci fonctionne à merveille :
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char *s;
    s = (char*) malloc (2 * sizeof(char) );
    free(s);
    s = (char*) malloc (5 * sizeof(char) );
    free(s);
    Oui mais moi j'essais de faire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char *s;
    s = (char*)malloc(20*sizeof(char));
    s = (char*)malloc(20*sizeof(char));
    free(s);
    Car si je fais free entre les deux mallocs, la valeur d'un attribut de ma structure change pour la valeur du deuxième s et etc... Bref je sais pas si je suis clair, mais en tout les cas c'est vrai que ça sens la grosse cagade !

  9. #9
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    Oui mais moi j'essais de faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char *s;
    s = (char*)malloc(20*sizeof(char));
    s = (char*)malloc(20*sizeof(char));
    free(s);
    Ben faut pas ! A quoi te sert la première allocation ?!?! tu perds (fuite mémoire) 20 octets.

    Bien sur, il y a d'autres lignes dans ton code et je pense que tu devrais nous présenter ton problème plus globalement. Là, comme ça, ça n'a aucun sens et on discute dans le vide.

    Je suis à peu près sur que tu n'alloues pas de la meilleure façon qui soit mais, sans autres infos ...
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  10. #10
    Expert éminent
    Avatar de transgohan
    Homme Profil pro
    Développeur Temps réel Embarqué
    Inscrit en
    Janvier 2011
    Messages
    3 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Temps réel Embarqué

    Informations forums :
    Inscription : Janvier 2011
    Messages : 3 146
    Points : 9 386
    Points
    9 386
    Par défaut
    Serais-ce que tu as besoin d'avoir accès en toute occasion à toutes les variables s allouées ? Si tel est le cas il va falloir penser à une dimension en plus pour stocker les autres.

    « Toujours se souvenir que la majorité des ennuis viennent de l'espace occupé entre la chaise et l'écran de l'ordinateur. »
    « Le watchdog aboie, les tests passent »

  11. #11
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    Cas de figure suivant (récurrent si je comprends bien) :

    • tu as déjà alloué une zone de 20 octets, s pointe donc dessus (s contient l'adresse mémoire de la zone allouée) et tu as rempli cette zone avec quelque chose
    • la Condition (dans ton code initial) est, une nouvelle fois, remplie


    Que veux-tu faire des "choses" que tu as "stockées" précédemment dans s (que tu as stockées dans la zone mémoire allouée et pointée par s pour être plus précis) ?

    Veux-tu les écraser ? (dans ce cas là, pas besoin de réallouer quoi que ce soit)

    Veux-tu une nouvelle zone de 20 octets pour y mettre autre chose et conserver ce que tu as mémorisé précédemment ? (dans ce cas là, il ne faut pas affecter à s la nouvelle zone allouée)

    C'est ce genre de renseignements qui manque. Parce que là, à chaque nouvelle allocation (et affectation à s) :

    1. tu provoques une fuite mémoire
    2. tu écrases/perds ce qui a été mis précédemment dans la zone allouée et affectée à s
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  12. #12
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 56
    Points : 35
    Points
    35
    Par défaut
    Merci de votre aide.

    En fait j'ai une structure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    typedef struct element element;
      struct element{
      char* def;
      char* val;
      struct element *nxt;
    };
    typedef element* llist;
    llist lst = NULL;
    Et la valeur de lst->val = la valeur de char* s.
    Une fois que j'ai fait ajouter(lst,s); la valeur de s je m'en fiche, mais si je fais free(s), au prochain malloc de s, la valeur de lst->val égale la nouvelle valeur de s.


    Donc en fait mon programme tel qu'il est là rajoute à chaque fois des malloc à s, *traitement sur s afin de le remplir*, je fais ajouter(lst,s), et je recommence.
    Bien sur ajouter() ajoute une cellule à lst car c'est une liste chainée.

    Il faudrait donc que je passe en matrice ?

  13. #13
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    Ton code peut se résumer à ça (attention, c'est très incomplet) :

    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
    int ajouter(llist liste, char *valeur)
    {
        element *new_element = malloc(sizeof(element));
     
        // ...
     
        new_element->val = valeur;
     
        // ...
    }
     
    int main(int argc, char *argv[])
    {
     
        llist liste = NULL;
        char *s;
     
        while (quelque_chose)
        {
            // ...
            s = malloc(20);
            // "remplissage" de s
            ajouter(liste,s);
        }
     
        // desallocation de LA LISTE
        // PAS DE DESALLOCATION DE S
     
        // ...
    }
    Si, dans ta fonction, tu affectes s à new-element->val, il s'agit d'une (re)copie de l'adresse de la zone allouée. Tu fais une copie d'entiers !

    Quand tu retournes dans l'appelant, il ne faut pas désallouer s. La zone mémoire initialement allouée à s est désormais référencée (pointée) par le champ val du nouvel élément de la liste.

    A la prochaine itération avec Condition à True, tu fais à nouveau une allocation qui sert au nouvel élément de la liste qui sera ajouté à la liste lors de l'appel à ajouter.

    Au final, dans ton cas, tu ne fais JAMAIS de désallocation de s. Par contre, c'est à la désallocation (globale) de la liste que ce sera traité : il faudra, pour chaque élément de la liste, aller désallouer le champ val (et sans doute aussi def).

    Je ne sais pas si je suis très clair ...
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  14. #14
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    Un bout de code minimaliste (j'ai remplacé la liste par un tableau, ça ne change rien au fond du problème) pour illustrer ce que j'ai, laborieusement, essayé d'expliquer précédemment :

    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
    #include <stdio.h>
    #include <stdlib.h>
     
    #define SIZE	3   // nombre de chaines manipulees (suffisant ici)
     
    int display_content(char *tableau[], int nb)
    {
        int i;
     
        printf("contenu tableau : ");
        for (i=0;i<nb;i++)
            printf("(%d,%p,\"%s\") ",i,tableau[i],tableau[i]);
        printf("\n");
    }
     
    int main(int argc,char *argv[])
    {
        char *tableau[SIZE];
        char *buffer;
        int nb = 0;
        int i;
     
        for (i=0;i<SIZE;i++)
        {
     
            // allocation, remplissage et affichage du buffer (mon "s")
            buffer = malloc(20);
            sprintf(buffer,"iter %d",i);
            printf("iteration %d buffer %p contient \"%s\"\n",i,buffer,buffer);
     
            // analogue a la fonction ajouter
            tableau[i] = buffer; nb++;
     
            // affichage du contenu du tableau
            display_content(tableau,nb);
        }
     
        // desallocation !
        for (i=0;i<SIZE;i++)
            free(tableau[i]);
    }
    à l'exécution

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    iteration 0 buffer 0x8959008 contient "iter 0"
    contenu tableau : (0,0x8959008,"iter 0") 
    iteration 1 buffer 0x8959020 contient "iter 1"
    contenu tableau : (0,0x8959008,"iter 0") (1,0x8959020,"iter 1") 
    iteration 2 buffer 0x8959038 contient "iter 2"
    contenu tableau : (0,0x8959008,"iter 0") (1,0x8959020,"iter 1") (2,0x8959038,"iter 2")
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  15. #15
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 56
    Points : 35
    Points
    35
    Par défaut
    Merci beaucoup pour tout ce travail plxpy.
    Là j'avoue que mon niveau C est très loin de savoir tout ça.
    Tu dis donc qu'un malloc n'implique pas forcément un free sur la même variable ! Ca je l'apprend.
    Merci pour toutes ces explications !

  16. #16
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    Tu dis donc qu'un malloc n'implique pas forcément un free sur la même variable !
    Ce n'est pas un but en soi mais, là, ça collait bien à ta façon de procéder.

    Si je reprends mon dernier post, ce que j'ai mis en rouge, l'important dans le"free(tableau[0])" c'est l'adresse "0x8959008", pas le contenu de la zone nom de la variable "pointeur".

    Si autre chose pointe sur la même zone (donc même adresse), disons buffer, free(buffer) fait exactement la même chose.
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

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

Discussions similaires

  1. [AC-2007] Scinder une table liée à plusieurs tables: Quid des Données?
    Par Dr_No dans le forum Modélisation
    Réponses: 3
    Dernier message: 28/05/2009, 15h54
  2. gestion mémoire sur plusieurs malloc
    Par contremaitre dans le forum C
    Réponses: 39
    Dernier message: 27/03/2008, 13h51
  3. malloc calloc realloc free
    Par lia20 dans le forum C
    Réponses: 7
    Dernier message: 26/05/2007, 15h22
  4. free/malloc
    Par Duguesclin dans le forum C
    Réponses: 3
    Dernier message: 09/01/2005, 19h04
  5. malloc et free
    Par barthelv dans le forum C
    Réponses: 3
    Dernier message: 22/07/2003, 18h34

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