Bonjour,
on vient de me demander si il etait vraiment nécéssaire d'appeler free() en fin de programme, en argumentant sur le fait que l'OS devait faire le ménage.
J'avoue que pour ma part j'ai toujours placer un free pour chacun de mes malloc avant le return, et je n'ai jamais vraiment cherché a savoir si c'etait si utile que ca (dans ma tete les blocs non-désalloués restaient bloqués jusqu'au reboot de la machine..)
Donc j'aimerai une réponse sur la question, que je ne meurt pas bête :)
Merci.
# mon avis.
Posté par TImaniac (site web personnel) . Évalué à 6.
Mais de manière générale c'est une bonne pratique, puisqu'il responsabilise le programmeur qui devient conscient des ressources qu'il utilise, et s'il faut bien son taf il pensera même à libérer la mémoire avant la fin du programme, quand il ne s'en sert plus, évitant ainsi de se retrouver avec une appli qui grossit, qui grossit, et qui fini par saturer l'OS qui n'a plus rien à lui donner à bouffer.
Donc de manière générale, les free c'est bien, mangez-en.
# Vraiment fin de programme
Posté par Zenitram (site web personnel) . Évalué à 4.
A la ligne 50, il quitte. Donc tu ne t'embettes pas a liberer les ressource, l'OS va le faire juste apres.
ton prog evolue.
Entre la ligne 49 et 50, tu inseres une boucle de deux heure qui fait une deuxieme chose, et qui n'a pas besoin de la memoire allouée avant la ligne 49.
Bilan : tu consommes de la memoire inutilement (celle allouée avant la ligne 49) pendant 2h.
Resumé : ca ne sert pas maintenant de le faire, mais peut-etre qu'un jour ca servira, dans le dout met free()
(bon, moi je fais delete() plutot, mais chacun son language ;-) )
[^] # Re: Vraiment fin de programme
Posté par doublehp (site web personnel) . Évalué à 2.
dans le main, j ai une double boucle for qui appelle une sous routine.
La sous routine fait elle meme une double boucle for apres avoir alloue plusieur des tableaux assez grands.
La routine alloue environ 4 tableaux de dimention variables ( des tableaux de 1 a 3D de taille totalement dynamique ) ... un enfer a allouer, et c est pire a desalouer.
Chaque for tourne environ 1000 tours. donc le main appelle 1000000 la sous routine. Laroutine alloue des tableaux de 1 a 10M. T imagine su je me gourre dans mes free ?
un free de trop, mal place, soit je libere un truc pas encore alloue, soit je libere une ressource dont je pourrai avoir besoin plus loin. Si je ne fait pas de free du tout, mon main appel 1000000 fois la sous routine qui alloue minimum 1Mo a chaque appel ... si je libere pas du tout, il me faudrait 1To de RAM ...
Donc meme si tout est libere apres execution, le truc risque de swapper plusieur jours ... dans la limite de la swap disponible ... et j ai deja 3Go de swap sur mes 350Go de disque.
Avec des free bien places, le tout s execute a peu pres bien avec un pic de consommation a environ 150Mo de RAM.
Enfin 150M, c est quand je manipule des images non compressees de 10Mo a la base. J ai en stoque une image de 80Mo ... elle j ai peur ... je crois que je vais jamais la traiter :)
( et je ne travailles qu en 8 bits per pixel).
Mais je vais tester de virer les free, je pense que ca va swapper severe avant meme de finire la premiere etape du traitement :)
# ca depend...
Posté par popopo333 . Évalué à 2.
sinon fais comme tu veux.
# Plop
Posté par cho7 (site web personnel) . Évalué à 4.
Ca confirme donc mon attitude : mettre autant de free qu'il y a de malloc.
question subsidiaire : ya t il un OS qui ne releaserait pas la mémoire en fin de programme ?
[^] # Re: Plop
Posté par WildChild . Évalué à 2.
[^] # Re: Plop
Posté par CoinKoin . Évalué à 2.
Donc, à mon avis, si tu trouves un OS de ce type, il ne mérite pas le titre d'OS.
[^] # Re: Plop
Posté par popopo333 . Évalué à 1.
[^] # Re: Plop
Posté par CoinKoin . Évalué à 2.
Pour moi, non. Et, dans ce cas-là, il faut soit considérer que toutes les applications font partie de l'OS, soit considérer qu'il n'y a pas d'OS du tout.
[^] # Re: Plop
Posté par Larry Cow . Évalué à 2.
Auquel cas, Linux n'est pas vraiment un OS alors, si? Parce qu'il me semble qu'une fork-bombe bien placée arrive (arrivait?) à faire des dégats...
[^] # Re: Plop
Posté par CoinKoin . Évalué à 2.
[^] # Re: Plop
Posté par Edouard Gomez (site web personnel) . Évalué à 2.
# Rapidité
Posté par CoinKoin . Évalué à 1.
Je n'ai pas fait de tests à ce sujet, ni été regarder le code Linux sur ce chapitre, mais je sais que le noyau 2.4, et certainement aussi le 2.6, alloue de la mémoire de façon contigue (zut, je n'ai pas de tréma, désolé...) au programme appelant, dans une zone préréservée à cet effet, du coup, la libération du fait du noyau se résumera à libérer cette zone, ce qui ira vite (en fait, comme cette zone a été réservée de toutes façons, le noyau devra forcément la libérer à la fin de l'exécution du processus), en revanche, si on libère les zones explicitement, on rajoute inutilement du code.
Bon, évidemment, on pourra me répondre que la terminaison d'un processus n'est généralement pas le moment où l'on a besoin d'un maximum de performances, puisque justement, la tâche est achevée, mais j'ai connu un cas contraire (un processus effectuait un fork(), le fils faisait une tâche complexe, puis revenait, et le père exploitait le résultat).
Bref, pour moi, si tu cherches des performances, évite ces free().
# en passant
Posté par B. franck . Évalué à 4.
pointée est une bonne manie...
(ça évite les double free car free(null) ne pose pas de problème)
[^] # Re: en passant
Posté par Florent C. . Évalué à 2.
[^] # Re: en passant
Posté par kd . Évalué à 2.
Un jour, ce bug furtif se réveillera à un endroit innatendu, et ce sera beaucoup de temps perdu à débugguer...
[^] # Re: en passant
Posté par . Takhi . Évalué à 3.
assert(monpointeur!=NULL);
free(monpointeur);
monpointeur=NULL;
avec la macro qui va bien tu peux avoir l'assertion en mode DEBUG et pas en mode Release
#ifdef DEBUG
#define MYFREE(ptr) assert(ptr!=NULL); free(ptr); ptr=NULL
#else
#define MYFREE(ptr) free(ptr); ptr=NULL
#endif
et tu invoques MYFREE au lieu de free
[^] # en repassant
Posté par schyzomarijks . Évalué à 2.
Si un autre programmeur fait un truc du genre :
if (m_ptr->value == 0 ) MYFREE(ptr);
return m_ptr;
Ta macro sera développée comme :
if (m_ptr->value == 0 ) assert(ptr!=NULL);
free(ptr);
ptr=NULL;
return m_ptr;
Là, tu as une destruction du pointeur quelque soit les conditions.
Ta macro doit être écrite :
#define MYFREE(ptr) { assert(ptr!=NULL); free(ptr); ptr=NULL; }
Mais d'une manière générale, il faut mieux éviter des macros et faire des fonctions inline (et oui, on peut faire du inline en C )
[^] # Re: en repassant
Posté par . Takhi . Évalué à 2.
par contre je tiens un peu au #define pour différentier les modes debug/release.
quelques exemples:
=> fonctions de trace que l'on peut virer en mode production/release
=> assertions
le code non debug ne comprendra pas les appels au fonctions de traces ce qui peut gagner pas mal de temps.
[^] # Re: en repassant
Posté par abgech . Évalué à 0.
#ifdef DEBUG
#define MYFREE(ptr) (assert(ptr!=NULL); free(ptr); ptr=NULL)
#else
#define MYFREE(ptr) (free(ptr); ptr=NULL)
#endif
On doit utiliser sans modération les ( ) dans les macros.
# L'OS ne fait pas tout ...
Posté par Florent C. . Évalué à 1.
Ou alors, il faut changer de langage de programmation et en utiliser un qui fournit des smart pointers ou un garbage collector ...
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.