Précédent   Forum du club des développeurs et IT Pro > C et C++ > C
C Forum d'entraide technique sur le langage C. Avant de poster -> F.A.Q. C, Avant de poster.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 01/01/2013, 20h29   #1
Fer2Lance
Invité régulier
 
Homme
Étudiant
Inscription : avril 2012
Messages : 46
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : avril 2012
Messages : 46
Points : 8
Points : 8
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.
Fer2Lance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/01/2013, 21h14   #2
Neckara
Rédacteur
 
Avatar de Neckara
 
Homme Denis
Étudiant
Inscription : décembre 2011
Messages : 2 539
Détails du profil
Informations personnelles :
Nom : Homme Denis
Localisation : France, Loire (Rhône Alpes)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : décembre 2011
Messages : 2 539
Points : 6 808
Points : 6 808
Envoyer un message via MSN à Neckara Envoyer un message via Skype™ à Neckara
Bonjour,

Il y aura en effet une fuite de mémoire.
Il faut faire un free par malloc.
__________________
Recherche devs C++ motivés et sérieux pour Last Dungeon.

Chaîne Youtube : Vidéos

Ma page DVP : http://neckara.developpez.com/
Neckara est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 02/01/2013, 09h56   #3
transgohan
Expert Confirmé
 
Avatar de transgohan
 
Homme Baptiste ROUSSEL
Développeur Temps réel Embarqué
Inscription : janvier 2011
Messages : 1 292
Détails du profil
Informations personnelles :
Nom : Homme Baptiste ROUSSEL
Localisation : France, Territoire de Belfort (Franche Comté)

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

Informations forums :
Inscription : janvier 2011
Messages : 1 292
Points : 2 847
Points : 2 847
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.
transgohan est déconnecté   Envoyer un message privé Réponse avec citation 11
Vieux 02/01/2013, 13h30   #4
Fer2Lance
Invité régulier
 
Homme
Étudiant
Inscription : avril 2012
Messages : 46
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : avril 2012
Messages : 46
Points : 8
Points : 8
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 ?
Fer2Lance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/01/2013, 13h47   #5
transgohan
Expert Confirmé
 
Avatar de transgohan
 
Homme Baptiste ROUSSEL
Développeur Temps réel Embarqué
Inscription : janvier 2011
Messages : 1 292
Détails du profil
Informations personnelles :
Nom : Homme Baptiste ROUSSEL
Localisation : France, Territoire de Belfort (Franche Comté)

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

Informations forums :
Inscription : janvier 2011
Messages : 1 292
Points : 2 847
Points : 2 847
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);

Citation:
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.
transgohan est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/01/2013, 14h18   #6
plxpy
Membre émérite
 
Avatar de plxpy
 
Homme
Ingénieur
Inscription : janvier 2009
Messages : 494
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 48
Localisation : France, Haute Garonne (Midi Pyrénées)

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

Informations forums :
Inscription : janvier 2009
Messages : 494
Points : 893
Points : 893
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.
plxpy est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 02/01/2013, 14h25   #7
transgohan
Expert Confirmé
 
Avatar de transgohan
 
Homme Baptiste ROUSSEL
Développeur Temps réel Embarqué
Inscription : janvier 2011
Messages : 1 292
Détails du profil
Informations personnelles :
Nom : Homme Baptiste ROUSSEL
Localisation : France, Territoire de Belfort (Franche Comté)

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

Informations forums :
Inscription : janvier 2011
Messages : 1 292
Points : 2 847
Points : 2 847
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.
transgohan est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/01/2013, 15h50   #8
Fer2Lance
Invité régulier
 
Homme
Étudiant
Inscription : avril 2012
Messages : 46
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : avril 2012
Messages : 46
Points : 8
Points : 8
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 !
Fer2Lance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/01/2013, 15h56   #9
plxpy
Membre émérite
 
Avatar de plxpy
 
Homme
Ingénieur
Inscription : janvier 2009
Messages : 494
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 48
Localisation : France, Haute Garonne (Midi Pyrénées)

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

Informations forums :
Inscription : janvier 2009
Messages : 494
Points : 893
Points : 893
Citation:
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 ...
plxpy est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/01/2013, 16h40   #10
transgohan
Expert Confirmé
 
Avatar de transgohan
 
Homme Baptiste ROUSSEL
Développeur Temps réel Embarqué
Inscription : janvier 2011
Messages : 1 292
Détails du profil
Informations personnelles :
Nom : Homme Baptiste ROUSSEL
Localisation : France, Territoire de Belfort (Franche Comté)

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

Informations forums :
Inscription : janvier 2011
Messages : 1 292
Points : 2 847
Points : 2 847
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.
transgohan est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/01/2013, 16h40   #11
plxpy
Membre émérite
 
Avatar de plxpy
 
Homme
Ingénieur
Inscription : janvier 2009
Messages : 494
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 48
Localisation : France, Haute Garonne (Midi Pyrénées)

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

Informations forums :
Inscription : janvier 2009
Messages : 494
Points : 893
Points : 893
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
plxpy est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/01/2013, 18h11   #12
Fer2Lance
Invité régulier
 
Homme
Étudiant
Inscription : avril 2012
Messages : 46
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : avril 2012
Messages : 46
Points : 8
Points : 8
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 ?
Fer2Lance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/01/2013, 19h02   #13
plxpy
Membre émérite
 
Avatar de plxpy
 
Homme
Ingénieur
Inscription : janvier 2009
Messages : 494
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 48
Localisation : France, Haute Garonne (Midi Pyrénées)

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

Informations forums :
Inscription : janvier 2009
Messages : 494
Points : 893
Points : 893
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 ...
plxpy est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/01/2013, 21h10   #14
plxpy
Membre émérite
 
Avatar de plxpy
 
Homme
Ingénieur
Inscription : janvier 2009
Messages : 494
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 48
Localisation : France, Haute Garonne (Midi Pyrénées)

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

Informations forums :
Inscription : janvier 2009
Messages : 494
Points : 893
Points : 893
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")
plxpy est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 04/01/2013, 21h07   #15
Fer2Lance
Invité régulier
 
Homme
Étudiant
Inscription : avril 2012
Messages : 46
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : avril 2012
Messages : 46
Points : 8
Points : 8
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 !
Fer2Lance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/01/2013, 21h28   #16
plxpy
Membre émérite
 
Avatar de plxpy
 
Homme
Ingénieur
Inscription : janvier 2009
Messages : 494
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 48
Localisation : France, Haute Garonne (Midi Pyrénées)

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

Informations forums :
Inscription : janvier 2009
Messages : 494
Points : 893
Points : 893
Citation:
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.
plxpy est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 12h05.


 
 
 
 
Partenaires

Hébergement Web