Free et structures ...

Free et structures ... - C - Programmation

Marsh Posté le 20-09-2005 à 15:32:30    

Salut,
 
Je voudrais savoir si quand j'ai un pointeur de structure, et que je le désalloue, dois-je désallouer aussi tout ce qu'il y a dans ma structure avant (si par exemple ma structure contient un tableau alloué) ?
 
par exe:
 
typedef struct {
 
 double *nombredeneuronesperdus;
 
}spliff;
 
/* et la par exmple j'alloue ma structure spliff bob_marley */
 
spliff *bob_marley = (spliff*)malloc(sizeof(spliff));
 
/** Et puis j'alloue  mon tableau de double */
bob_marley->nombredeneuronesperdus = (double*)malloc(sizeof(double)*10000000000000000000000);
 
...
 
Je voudrais savoir si, lors de la libération :
 
1) Est ce que  
 
free(bob_marley);  
 
suffit ?
 
2) Ou bien dois-je nécéssairement faire :
 
free(bob_marley->nombredeneuronesperdus);
 
//et ensuite
 
free(bob_marley);
 
??
 
 
merci par avance

Message cité 2 fois
Message édité par in_your_phion le 20-09-2005 à 15:34:59
Reply

Marsh Posté le 20-09-2005 à 15:32:30   

Reply

Marsh Posté le 20-09-2005 à 15:34:25    

ca doit dépendre des compilateurs mais normalement oui il faut le faire

Reply

Marsh Posté le 20-09-2005 à 16:22:51    

in_your_phion a écrit :

Je voudrais savoir si quand j'ai un pointeur de structure, et que je le désalloue, dois-je désallouer aussi tout ce qu'il y a dans ma structure avant (si par exemple ma structure contient un tableau alloué) ?


#2. Le principe est simple. Pour chaque malloc()/realloc()/calloc(), il doit y avoir un free.
 
Et n'oublie pas de tester les valeurs retournées par malloc() avant de les utiliser...

Message cité 1 fois
Message édité par Emmanuel Delahaye le 20-09-2005 à 16:24:25

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 20-09-2005 à 17:30:23    

Emmanuel Delahaye a écrit :

#2. Le principe est simple. Pour chaque malloc()/realloc()/calloc(), il doit y avoir un free.
 
Et n'oublie pas de tester les valeurs retournées par malloc() avant de les utiliser...


 
ok merci les gars ... bon ben c'est quand meme ennuyeux de devoir faire tout un tas de desallocations à chaque fois.
 
Juste une autre p'tite question rapport au free ... Si j'ai une fonction qui fait un free, dois-je obligatoirement passer en argument un pointeur ?
 
par ex
 
si j'ai :
 
int **my_array;
 
est ce que ma fonction free doit etre :
 
1)
 
void nuke_array (int **array) {
free(*array);
*array = NULL;
}
 
//et l'appel
nuke_array(my_array);
 
 
 
2) ou alors:
 
void nuke_array (int ***array) {
free(**array);
**array=NULL;
}
 
 
//appel
nuke_array(&my_array);
 
 
merci ..

Message cité 1 fois
Message édité par in_your_phion le 20-09-2005 à 17:40:17
Reply

Marsh Posté le 20-09-2005 à 17:56:40    

Si j'ai bien compris, array est un tableau à deux dimensions dont chaque dimension est allouée avec malloc().
 
Du coup, j'aurais plutôt voté un truc du genre :
 

Code :
  1. void nuke_array(int ***array, int lines)
  2. {
  3.     if ( *array )
  4.     {
  5.         int i;
  6.         for(i = 0; i<lines; i++)
  7.         {
  8.             free((*array)[i]), (*array)[i] = NULL;
  9.         }
  10.         free(*array), *array = NULL;
  11.     }
  12. }


 
Que tu appelles avec un : "nuke_array(&ton_tableau, nombre_de_lignes);"
 
Mais il faudrait que tu nous montres comment tu définis array pour en être sûr.

Message cité 2 fois
Message édité par Elmoricq le 20-09-2005 à 17:58:22
Reply

Marsh Posté le 20-09-2005 à 18:02:52    

Elmoricq a écrit :

Mais il faudrait que tu nous montres comment tu définis array pour en être sûr.


 
En fait c'est un faux tableau, j'utilise quasiment jamais des vrais tablos 2d :
 
int **array = (int*)malloc(sizeof(int)*TAILLE_X*TAILLE_Y);
 
En fait free c'est une opération de modification ? si c'est ça je dois passer un pointeur alors (donc un *** dans mon cas), nan ?


Message édité par in_your_phion le 20-09-2005 à 18:09:23
Reply

Marsh Posté le 20-09-2005 à 18:07:46    

Euh, tu es au courant ton tableau est à une seule dimension, là, et qu'il te suffit de faire :
 

Code :
  1. int *array = malloc( TAILLE_X * TAILLE_Y * sizeof *array);
  2. if ( array ) {
  3.     ...
  4. }


 
Et, du coup, free(array) suffit largement.
 
EDIT :

Citation :

En fait free c'est une opération de modification ? si c'est ça je dois passer un pointeur alors (donc un *** dans mon cas), nan ?


 
Ce n'est pas pour free() qu'on doit passer l'adresse, c'est pour le array = NULL
 
 

Citation :

ps : que fait le test  
 
if (*array) ?


 
Pareil que "if ( *array != NULL )"

Message cité 1 fois
Message édité par Elmoricq le 20-09-2005 à 18:09:41
Reply

Marsh Posté le 20-09-2005 à 18:14:15    

Elmoricq a écrit :

Euh, tu es au courant ton tableau est à une seule dimension, là, et qu'il te suffit de faire :
 

Code :
  1. int *array = malloc( TAILLE_X * TAILLE_Y * sizeof *array);
  2. if ( array ) {
  3.     ...
  4. }


 
Et, du coup, free(array) suffit largement.
 
EDIT :

Citation :

En fait free c'est une opération de modification ? si c'est ça je dois passer un pointeur alors (donc un *** dans mon cas), nan ?


 
Ce n'est pas pour free() qu'on doit passer l'adresse, c'est pour le array = NULL
 
 

Citation :

ps : que fait le test  
 
if (*array) ?


 
Pareil que "if ( *array != NULL )"


 
 
ok merci bien :) .. j'ai enlevé ce dernier commentaire car j'ai compris avec ta réponse entre temps. Euh, non enfin mon tableau set à deux dimensions  :cry:  :pt1cable:  :pt1cable:  .. c'est juste que c'est de mémoire que je me rappelle ce probleme, j'ai pas vraiemtn d'exemple concret. Mais par rapport a ce que tu dis : si je fais juste un free ce n'est pas considéré comme une modif ? et l'assignation NULL oui ?

Reply

Marsh Posté le 20-09-2005 à 18:18:27    

free() n'affecte pas la variable, il permet simplement de libérer la mémoire réservée pointée par la variable (mais il ne la rend pas au système, il ne fait que la rendre au programme lui-même).
La mémoire pointée par la variable peut donc potentiellement être écrasée par n'importe quoi dans ton programme, puisque plus rien ne la réserve.
Par conséquent, on prend l'habitude d'affecter NULL à la variable ainsi libérée, histoire d'éviter les potentiels comportements indéfinis si par malheur la variable venait à être utilisée après un free() (comportement indéfini, l'un des bugs les plus difficiles à détecter :sweat: )
 
En revanche, affecter une valeur à une variable, fut-ce un pointeur, est évidemment une modification.


Message édité par Elmoricq le 20-09-2005 à 18:20:49
Reply

Marsh Posté le 20-09-2005 à 19:02:08    

in_your_phion a écrit :

ok merci les gars ... bon ben c'est quand meme ennuyeux de devoir faire tout un tas de desallocations à chaque fois.


C'est pour ça qu'en principe, on utilise des constructeurs / destructeurs qui font le boulot en silence...
 
http://mapage.noos.fr/emdel/tad.htm

Citation :


Juste une autre p'tite question rapport au free ... Si j'ai une fonction qui fait un free, dois-je obligatoirement passer en argument un pointeur ?
 
par ex
 
si j'ai :
 
int **my_array;
 
est ce que ma fonction free doit etre :
 
1)
 
void nuke_array (int **array) {
free(*array);
*array = NULL;
}
 
//et l'appel
nuke_array(my_array);
 
 
 
2) ou alors:
 
void nuke_array (int ***array) {
free(**array);
**array=NULL;
}
 
 
//appel
nuke_array(&my_array);
 
 
merci ..


En fait, tu veux savoir si on doit mettre le pointeur à NULL et comment on fait...
 
Il est effectivement recommandé de remettre un pointeur qui ne pointe plus sur un bloc valide (donc après un free) à NULL.
 
J'ai l'habitude d'écrire ceci :  
 
   free (p), p = NULL;
 
Si on utilise une fonction, on peut faire de différentes façons :  


  T *p = xx_create();
<...>
 
/* 1 */
   xx_delete_1 (p), p = NULL;
 
/* 2 */
   p = xx_delete_2 (p);
 
/* 3 */
   xx_delete_3 (&p);
 

Avec


   void xx_delete_1 (T *p);
   T *xx_delete_2 (T *p);
   void xx_delete_3 (T **pp);


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 20-09-2005 à 19:02:08   

Reply

Marsh Posté le 20-09-2005 à 19:03:51    

Elmoricq a écrit :


       free(*array), *array = NULL;




Héhé ! Je vois que je commence à faire des adeptes !


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 20-09-2005 à 19:57:37    

in_your_phion a écrit :


 
....Ou bien dois-je nécéssairement faire :
 
free(bob_marley->nombredeneuronesperdus);
 
//et ensuite
 
free(bob_marley);
 
??


 
Welcome to the C world.

Reply

Marsh Posté le 20-09-2005 à 22:59:38    

Emmanuel Delahaye a écrit :

Héhé ! Je vois que je commence à faire des adeptes !


 
J'initialisais toujours à NULL (on apprend vite à le faire après de longues séances de debug :sweat: ), mais sur deux lignes, je ne connaissais pas cette syntaxe avec la virgule avant.
Ca donne l'impression d'une seule action, donc c'est plus lisible, alors j'ai effectivement adopté la syntaxe.  
 [:romf]

Reply

Marsh Posté le 21-09-2005 à 08:38:28    

Elmoricq a écrit :

JCa donne l'impression d'une seule action, donc c'est plus lisible.


Exactement. Autre avantage, GNUIndent laisse la ligne entière, ce qui renforce l'impression de cohésion.


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 21-09-2005 à 09:47:38    

Elmoricq a écrit :

J'initialisais toujours à NULL (on apprend vite à le faire après de longues séances de debug :sweat: ), mais sur deux lignes, je ne connaissais pas cette syntaxe avec la virgule avant.
 [:romf]


 
Pourtant on utilise beaucoup la virgule (opérateur séquentiel) en C comme ici  
=> "appel_fonction(a, b, c)"  
 
ou bien ici
=> "int a, b, c".
 
Tu peux même écrire des trucs inutiles style  
=> "a=(5, 6, 7 + 3)"
 :pt1cable:  :pt1cable:  :pt1cable:

Message cité 1 fois
Message édité par Sve@r le 21-09-2005 à 09:52:53
Reply

Marsh Posté le 21-09-2005 à 09:54:36    

Sve@r a écrit :

Tu peux même écrire des trucs inutiles style  
=> "a=(5, 6, 7 + 3)"


 
tiens, j'avais jamais vu.
comment est résolue l'expression ?


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 21-09-2005 à 09:59:19    

blackgoddess a écrit :

tiens, j'avais jamais vu.
comment est résolue l'expression ?


 
Ben déjà j'ai mis des parenthèses parce que je ne connais pas les priorités par coeur (priorité du "=" par rapport à la virgule).
Donc, l'expression évalue la parenthèse en premier et l'expression "7 + 3" est la dernière à en ressortir (opérateur "séquentiel" )
Cette expression est ensuite stockée dans "a" (opérateur d'affectation) => a vaut 10


Message édité par Sve@r le 21-09-2005 à 10:00:44
Reply

Marsh Posté le 21-09-2005 à 09:59:28    

J'imagine que a vaudra successivement 5, 6 puis 7+3.
Ce qui est inutile, comme l'a dit Sve@r ;)
 
EDIT : grillé :sweat:


Message édité par Elmoricq le 21-09-2005 à 09:59:55
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed