+ Répondre à la discussion
Affichage des résultats 1 à 16 sur 16
  1. #1
    Candidat au titre de Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    avril 2012
    Messages
    55
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : avril 2012
    Messages : 55
    Points : 10
    Points
    10

    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 :
    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
    Expert Confirmé Sénior


    Homme Profil pro
    Étudiant
    Inscrit en
    décembre 2011
    Messages
    5 109
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 21
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2011
    Messages : 5 109
    Points : 15 173
    Points
    15 173

    Par défaut

    Bonjour,

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

  3. #3
    Expert Confirmé Sénior
    Avatar de transgohan
    Homme Profil pro
    Développeur Temps réel Embarqué
    Inscrit en
    janvier 2011
    Messages
    1 769
    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 : 1 769
    Points : 4 806
    Points
    4 806

    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.

  4. #4
    Candidat au titre de Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    avril 2012
    Messages
    55
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : avril 2012
    Messages : 55
    Points : 10
    Points
    10

    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 :
    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 Confirmé Sénior
    Avatar de transgohan
    Homme Profil pro
    Développeur Temps réel Embarqué
    Inscrit en
    janvier 2011
    Messages
    1 769
    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 : 1 769
    Points : 4 806
    Points
    4 806

    Par défaut

    Malheureux on ne désaloue pas un char. Tu tentes de faire un truc du genre :
    Code c :
    1
    2
    char s = 'a';
    free(s);
    Ce qui est différent de :
    Code c :
    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 :
    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.

  6. #6
    Modérateur
    Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    janvier 2009
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    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 : 640
    Points : 1 155
    Points
    1 155

    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.

  7. #7
    Expert Confirmé Sénior
    Avatar de transgohan
    Homme Profil pro
    Développeur Temps réel Embarqué
    Inscrit en
    janvier 2011
    Messages
    1 769
    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 : 1 769
    Points : 4 806
    Points
    4 806

    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.

  8. #8
    Candidat au titre de Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    avril 2012
    Messages
    55
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : avril 2012
    Messages : 55
    Points : 10
    Points
    10

    Par défaut

    Citation Envoyé par transgohan Voir le message
    Ceci fonctionne à merveille :
    Code c :
    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 :
    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
    Modérateur
    Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    janvier 2009
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    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 : 640
    Points : 1 155
    Points
    1 155

    Par défaut

    Oui mais moi j'essais de faire ceci :
    Code :
    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 ...

  10. #10
    Expert Confirmé Sénior
    Avatar de transgohan
    Homme Profil pro
    Développeur Temps réel Embarqué
    Inscrit en
    janvier 2011
    Messages
    1 769
    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 : 1 769
    Points : 4 806
    Points
    4 806

    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.

  11. #11
    Modérateur
    Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    janvier 2009
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    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 : 640
    Points : 1 155
    Points
    1 155

    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

  12. #12
    Candidat au titre de Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    avril 2012
    Messages
    55
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : avril 2012
    Messages : 55
    Points : 10
    Points
    10

    Par défaut

    Merci de votre aide.

    En fait j'ai une structure :
    Code :
    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
    Modérateur
    Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    janvier 2009
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    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 : 640
    Points : 1 155
    Points
    1 155

    Par défaut

    Ton code peut se résumer à ça (attention, c'est très incomplet) :

    Code :
    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 ...

  14. #14
    Modérateur
    Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    janvier 2009
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    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 : 640
    Points : 1 155
    Points
    1 155

    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 :
    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 :
    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")

  15. #15
    Candidat au titre de Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    avril 2012
    Messages
    55
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : avril 2012
    Messages : 55
    Points : 10
    Points
    10

    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
    Modérateur
    Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    janvier 2009
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    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 : 640
    Points : 1 155
    Points
    1 155

    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.

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

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
  •