Est-il jamais acceptable d'avoir une fuite de mémoire dans votre application C ou C ++?
Et si vous allouez de la mémoire et l'utilisez jusqu'à la toute dernière ligne de code de votre application (par exemple, le destructeur d'un objet global)? Tant que la consommation de mémoire n'augmente pas avec le temps, est-il OK de faire confiance au système d'exploitation pour libérer votre mémoire pour vous lorsque votre application se termine (sous Windows, Mac et Linux)? Considérez-vous même cela comme une véritable fuite de mémoire si la mémoire était utilisée en continu jusqu'à ce qu'elle soit libérée par le système d'exploitation.
Et si une bibliothèque tierce vous imposait cette situation? Refuserait-elle d'utiliser cette bibliothèque tierce, quelle que soit sa grandeur?
Je ne vois qu'un inconvénient pratique, c'est que ces fuites bénignes apparaîtront avec des outils de détection de fuites de mémoire comme des faux positifs.
la source
Réponses:
Non.
En tant que professionnels, la question que nous ne devrions pas nous poser est: "Est-ce que c'est toujours OK de faire ça?" mais plutôt "Y a-t-il jamais une bonne raison de le faire?" Et "traquer cette fuite de mémoire est une douleur" n'est pas une bonne raison.
J'aime garder les choses simples. Et la règle simple est que mon programme ne doit avoir aucune fuite de mémoire.
Cela rend ma vie aussi simple. Si je détecte une fuite de mémoire, je l'élimine, plutôt que de parcourir une structure d'arbre de décision élaborée pour déterminer s'il s'agit d'une fuite de mémoire "acceptable".
C'est similaire aux avertissements du compilateur - l'avertissement sera-t-il fatal à mon application particulière? Peut être pas.
Mais c'est finalement une question de discipline professionnelle. Tolérer les avertissements du compilateur et tolérer les fuites de mémoire est une mauvaise habitude qui me mordra finalement à l'arrière.
Pour pousser les choses à l'extrême, serait-il jamais acceptable qu'un chirurgien laisse un équipement d'exploitation à l'intérieur d'un patient?
Bien qu'il soit possible qu'une circonstance se produise où le coût / risque de retirer cette pièce d'équipement dépasse le coût / risque de le laisser, et qu'il pourrait y avoir des circonstances où il était inoffensif, si je voyais cette question publiée sur SurgeonOverflow.com et vu une réponse autre que «non», cela minerait sérieusement ma confiance dans la profession médicale.
-
Si une bibliothèque tierce m'imposait cette situation, cela me conduirait à soupçonner sérieusement la qualité globale de la bibliothèque en question. Ce serait comme si je testais au volant d'une voiture et que je trouvais quelques rondelles et écrous desserrés dans l'un des porte-gobelets - ce n'est peut-être pas un gros problème en soi, mais cela dépeint un manque d'engagement envers la qualité, donc j'envisagerais des alternatives.
la source
Je ne considère pas que ce soit une fuite de mémoire à moins que la quantité de mémoire «utilisée» ne cesse de croître. Avoir de la mémoire non libérée, bien que non idéal, n'est pas un gros problème à moins que la quantité de mémoire requise ne cesse de croître.
la source
Obtenons nos définitions correctes, d'abord. Une fuite de mémoire survient lorsque la mémoire est allouée dynamiquement, par exemple avec
malloc()
, et toutes les références à la mémoire sont perdues sans le libre correspondant. Un moyen simple d'en créer un est comme ceci:Notez que chaque fois autour de la boucle while (1), 1024 (+ overhead) octets sont alloués et la nouvelle adresse assignée à vp; il n'y a plus de pointeur vers les blocs mallocédés précédents. Ce programme est garanti pour fonctionner jusqu'à ce que le tas soit épuisé, et il n'y a aucun moyen de récupérer la mémoire malloc'ed. La mémoire "fuit" hors du tas, pour ne plus jamais être vue.
Mais ce que vous décrivez ressemble à
Vous allouez la mémoire, travaillez avec elle jusqu'à la fin du programme. Ce n'est pas une fuite de mémoire; cela n'altère pas le programme, et toute la mémoire sera récupérée automatiquement à la fin du programme.
En règle générale, vous devez éviter les fuites de mémoire. Premièrement, parce que, comme l'altitude au-dessus de vous et le carburant au hangar, la mémoire qui a fui et qui ne peut pas être récupérée est inutile; deuxièmement, il est beaucoup plus facile de coder correctement, sans fuite de mémoire, au début que de trouver une fuite de mémoire plus tard.
la source
malloc
trop de mémoire, c'est une mauvaise chose. Ce n'est toujours pas une fuite . Ce n'est pas une fuite tant que ce n'est pas unemalloc
mémoire d à laquelle la référence est perdue.En théorie non, en pratique cela dépend .
Cela dépend vraiment de la quantité de données sur lesquelles le programme travaille, de la fréquence à laquelle le programme est exécuté et de son exécution permanente ou non.
Si j'ai un programme rapide qui lit une petite quantité de données fait un calcul et se termine, une petite fuite de mémoire ne sera jamais remarquée. Étant donné que le programme ne s'exécute pas très longtemps et n'utilise qu'une petite quantité de mémoire, la fuite sera faible et libérée lorsque le programme existera.
D'un autre côté, si j'ai un programme qui traite des millions d'enregistrements et s'exécute pendant une longue période, une petite fuite de mémoire peut faire baisser la machine avec suffisamment de temps.
Quant aux bibliothèques tierces qui ont des fuites, si elles causent un problème, corrigez la bibliothèque ou trouvez une meilleure alternative. Si cela ne pose pas de problème, est-ce vraiment important?
la source
Beaucoup de gens semblent avoir l'impression qu'une fois que vous libérez de la mémoire, elle est instantanément retournée au système d'exploitation et peut être utilisée par d'autres programmes.
Ce n'est pas vrai. Les systèmes d'exploitation gèrent généralement la mémoire dans les pages 4KiB.
malloc
et d'autres types de gestion de la mémoire récupèrent les pages du système d'exploitation et les sous-gèrent comme bon leur semble. Il est très probable quefree()
les pages ne retournent pas au système d'exploitation, en supposant que votre programme malloc plus de mémoire plus tard.Je ne dis pas que
free()
ne retourne jamais de mémoire au système d'exploitation. Cela peut se produire, en particulier si vous libérez de grandes étendues de mémoire. Mais il n'y a aucune garantie.Le fait important: si vous ne libérez pas de mémoire dont vous n'avez plus besoin, les autres mallocs sont garantis pour consommer encore plus de mémoire. Mais si vous libérez d'abord, malloc pourrait réutiliser la mémoire libérée à la place.
Qu'est-ce que cela signifie dans la pratique? Cela signifie que si vous savez que votre programme ne nécessitera plus de mémoire à partir de maintenant (par exemple, il est en phase de nettoyage), libérer de la mémoire n'est pas si important. Cependant, si le programme peut allouer plus de mémoire ultérieurement, vous devez éviter les fuites de mémoire, en particulier celles qui peuvent se produire à plusieurs reprises.
Consultez également ce commentaire pour plus de détails sur les raisons pour lesquelles la libération de mémoire juste avant la fin est mauvaise.
Un intervenant ne semblait pas comprendre que l'appel
free()
ne permet pas automatiquement à d'autres programmes d'utiliser la mémoire libérée. Mais c'est tout l'intérêt de cette réponse!Donc, pour convaincre les gens, je vais montrer un exemple où free () fait très peu de bien. Pour rendre les calculs faciles à suivre, je vais faire comme si le système d'exploitation gère la mémoire sur des pages de 4000 octets.
Supposons que vous allouez dix mille blocs de 100 octets (pour simplifier, j'ignorerai la mémoire supplémentaire qui serait requise pour gérer ces allocations). Cela consomme 1 Mo ou 250 pages. Si vous libérez ensuite 9000 de ces blocs au hasard, il ne vous reste que 1000 blocs - mais ils sont dispersés partout. Statistiquement, environ 5 des pages seront vides. Les 245 autres auront chacun au moins un bloc alloué. Cela représente 980 Ko de mémoire, qui ne peuvent pas être récupérés par le système d'exploitation - même si vous n'avez plus que 100 Ko alloués!
D'un autre côté, vous pouvez désormais malloc () 9000 blocs supplémentaires sans augmenter la quantité de mémoire que votre programme est en train de bloquer.
Même s'il est techniquement
free()
possible de restituer de la mémoire au système d'exploitation, il peut ne pas le faire.free()
doit parvenir à un équilibre entre un fonctionnement rapide et une économie de mémoire. Et d'ailleurs, un programme qui a déjà alloué beaucoup de mémoire puis libéré il est probable qu'il le fasse à nouveau. Un serveur Web doit gérer requête après requête après requête - il est logique de garder une certaine mémoire "disponible" afin que vous n'ayez pas besoin de demander au système d'exploitation de la mémoire tout le temps.la source
Il n'y a rien de mal sur le plan conceptuel à faire nettoyer le système d'exploitation après l'exécution de l'application.
Cela dépend vraiment de l'application et de la façon dont elle sera exécutée. Les fuites qui se produisent continuellement dans une application qui doit s'exécuter pendant des semaines doivent être prises en charge, mais un petit outil qui calcule un résultat sans un besoin de mémoire trop élevé ne devrait pas être un problème.
Il y a une raison pour laquelle de nombreux langages de script ne récupèrent pas les références cycliques ... pour leurs modèles d'utilisation, ce n'est pas un problème réel et serait donc autant un gaspillage de ressources que la mémoire gaspillée.
la source
Je crois que la réponse est non, ne permettez jamais une fuite de mémoire, et j'ai quelques raisons que je n'ai pas vues explicitement énoncées. Il y a de grandes réponses techniques ici mais je pense que la vraie réponse dépend de raisons plus sociales / humaines.
(Tout d'abord, notez que, comme d'autres l'ont mentionné, une véritable fuite se produit lorsque votre programme, à tout moment, perd la trace des ressources mémoire qu'il a allouées. En C, cela se produit lorsque vous accédez
malloc()
à un pointeur et laissez ce pointeur quitter la portée sans faire defree()
première.)Le nœud important de votre décision ici est l'habitude. Lorsque vous codez dans un langage qui utilise des pointeurs, vous allez utiliser beaucoup de pointeurs . Et les pointeurs sont dangereux; ils sont le moyen le plus simple d'ajouter toutes sortes de problèmes graves à votre code.
Lorsque vous codez, parfois vous allez être sur le ballon et parfois vous allez être fatigué ou fou ou inquiet. Pendant ces moments quelque peu distraits, vous codez davantage sur le pilote automatique. L'effet du pilote automatique ne fait pas la différence entre un code unique et un module dans un projet plus vaste. Pendant ces périodes, les habitudes que vous établissez sont celles qui se retrouveront dans votre base de code.
Donc non, ne permettez jamais de fuites de mémoire pour la même raison que vous devriez toujours vérifier vos angles morts lorsque vous changez de voie, même si vous êtes la seule voiture sur la route en ce moment. Pendant les moments où votre cerveau actif est distrait, de bonnes habitudes sont tout ce qui peut vous éviter des faux pas désastreux.
Au-delà du problème de «l'habitude», les pointeurs sont complexes et nécessitent souvent beaucoup de puissance cérébrale pour être suivis mentalement. Il est préférable de ne pas «brouiller l'eau» quand il s'agit de votre utilisation des pointeurs, en particulier lorsque vous êtes nouveau dans la programmation.
Il y a aussi un aspect plus social. En utilisant correctement
malloc()
etfree()
, toute personne qui regarde votre code sera à l'aise; vous gérez vos ressources. Si vous ne le faites pas, cependant, ils suspecteront immédiatement un problème.Peut-être que vous avez compris que la fuite de mémoire ne fait rien de mal dans ce contexte, mais chaque responsable de votre code devra également le comprendre dans sa tête lorsqu'il lira ce morceau de code. En utilisant,
free()
vous supprimez la nécessité de même considérer le problème.Enfin, la programmation consiste à écrire un modèle mental d'un processus dans un langage non ambigu afin qu'une personne et un ordinateur puissent parfaitement comprendre ce processus. Un élément essentiel d'une bonne pratique de programmation n'est jamais d'introduire une ambiguïté inutile.
La programmation intelligente est flexible et générique. Une mauvaise programmation est ambiguë.
la source
new
, ce qui élimine immédiatement la plupart des fuites de mémoire. Seulement si vous devez absolument l'utilisernew
. Le résultatnew
doit être immédiatement placé dans un pointeur intelligent. Si vous suivez ces deux règles, vous ne perdrez tout simplement jamais de mémoire (sauf bogue dans une bibliothèque). Le seul cas restant est celui desshared_ptr
cycles, auquel cas il faut savoir l'utiliserweak_ptr
.Je pense que dans votre situation, la réponse peut être que tout va bien. Mais vous devez absolument documenter que la fuite de mémoire est une décision consciente. Vous ne voulez pas qu'un programmeur de maintenance vous accompagne, gifle votre code dans une fonction et l'appelle un million de fois. Donc, si vous décidez qu'une fuite est correcte, vous devez la documenter (EN GRANDES LETTRES) pour quiconque pourrait devoir travailler sur le programme à l'avenir.
S'il s'agit d'une bibliothèque tierce, vous pouvez être piégé. Mais documentez certainement que cette fuite se produit.
Mais fondamentalement, si la fuite de mémoire est une quantité connue comme un tampon de 512 Ko ou quelque chose d'autre, ce n'est pas un problème. Si la fuite de mémoire continue de croître comme chaque fois que vous appelez une bibliothèque, votre mémoire augmente de 512 Ko et n'est pas libérée, alors vous pouvez avoir un problème. Si vous le documentez et contrôlez le nombre d'exécutions de l'appel, cela peut être gérable. Mais alors vous avez vraiment besoin de documentation parce que si 512 n'est pas beaucoup, 512 plus d'un million d'appels, c'est beaucoup.
Vous devez également vérifier la documentation de votre système d'exploitation. S'il s'agissait d'un périphérique intégré, il peut y avoir des systèmes d'exploitation qui ne libèrent pas toute la mémoire d'un programme qui se ferme. Je ne suis pas sûr, ce n'est peut-être pas vrai. Mais cela vaut la peine d'être examiné.
la source
Je vais donner la réponse impopulaire mais pratique qu'il est toujours mal de libérer de la mémoire à moins que cela ne réduise l'utilisation de la mémoire de votre programme . Par exemple, un programme qui effectue une seule allocation ou une série d'allocations pour charger l'ensemble de données qu'il utilisera pendant toute sa durée de vie n'a pas besoin de libérer quoi que ce soit. Dans le cas le plus courant d'un grand programme avec des besoins en mémoire très dynamiques (pensez à un navigateur Web), vous devez évidemment libérer la mémoire que vous n'utilisez plus dès que vous le pouvez (par exemple, fermer un onglet / document / etc.) , mais il n'y a aucune raison de libérer quoi que ce soit lorsque l'utilisateur sélectionne des clics sur "Quitter", ce qui nuit en fait à l'expérience utilisateur.
Pourquoi? Pour libérer de la mémoire, il faut toucher la mémoire. Même si l'implémentation malloc de votre système ne stocke pas de métadonnées adjacentes aux blocs de mémoire alloués, vous allez probablement parcourir des structures récursives juste pour trouver tous les pointeurs que vous devez libérer.
Supposons maintenant que votre programme fonctionne avec un grand volume de données, mais qu'il n'en ait pas touché la majeure partie depuis un certain temps (encore une fois, le navigateur Web est un excellent exemple). Si l'utilisateur exécute un grand nombre d'applications, une bonne partie de ces données a probablement été échangée sur le disque. Si vous quittez simplement (0) ou revenez de main, il se ferme instantanément. Grande expérience utilisateur. Si vous vous donnez la peine d'essayer de tout libérer, vous pouvez passer 5 secondes ou plus à échanger toutes les données, pour les jeter immédiatement après. Perte de temps de l'utilisateur. Perte de la vie de la batterie de l'ordinateur portable. Déchets d'usure sur le disque dur.
Ce n'est pas seulement théorique. Chaque fois que je me retrouve avec trop d'applications chargées et que le disque se met à battre, je ne pense même pas à cliquer sur "quitter". J'arrive à un terminal aussi vite que possible et je tape killall -9 ... parce que je sais que "exit" ne fera qu'empirer les choses.
la source
Je suis sûr que quelqu'un peut trouver une raison de dire oui, mais ce ne sera pas moi. Au lieu de dire non, je vais dire que cela ne devrait pas être une question oui / non. Il existe des moyens de gérer ou de contenir les fuites de mémoire, et de nombreux systèmes en disposent.
Il existe des systèmes de la NASA sur des appareils qui quittent la terre qui planifient cela. Les systèmes redémarrent automatiquement de temps en temps afin que les fuites de mémoire ne deviennent pas fatales à l'opération globale. Juste un exemple de confinement.
la source
Si vous allouez de la mémoire et l'utilisez jusqu'à la dernière ligne de votre programme, ce n'est pas une fuite. Si vous allouez de la mémoire et l'oubliez, même si la quantité de mémoire n'augmente pas, c'est un problème. Cette mémoire allouée mais inutilisée peut ralentir ou pas exécuter d'autres programmes.
la source
Je peux compter d'une part le nombre de fuites "bénignes" que j'ai vues au fil du temps.
La réponse est donc un oui très qualifié.
Un exemple. Si vous avez une ressource singleton qui a besoin d'un tampon pour stocker une file d'attente circulaire ou deque mais ne sait pas quelle taille le tampon devra être et ne peut pas se permettre le surcoût de verrouillage ou de chaque lecteur, alors allouer un tampon doublant exponentiellement mais ne pas libérer les anciens entraînera une fuite de mémoire limitée par file d'attente / deque. L'avantage pour ceux-ci est qu'ils accélèrent considérablement chaque accès et peuvent changer l'asymptotique des solutions multiprocesseurs en ne risquant jamais de contester un verrou.
J'ai vu cette approche très utile pour les choses avec des nombres très clairement fixés tels que les deques de vol de travail par processeur, et dans une bien moindre mesure dans le tampon utilisé pour maintenir l'
/proc/self/maps
état singleton dans le récupérateur de déchets conservateur de Hans Boehm pour C / C ++, qui est utilisé pour détecter les jeux de racines, etc.Bien que techniquement une fuite, ces deux cas soient limités en taille et dans le travail circulaire évolutif volant le cas deque, il y a une énorme amélioration des performances en échange d'un facteur borné de 2 augmentation de l'utilisation de la mémoire pour les files d'attente.
la source
Si vous allouez un tas de tas au début de votre programme et que vous ne le libérez pas lorsque vous quittez, ce n'est pas une fuite de mémoire en soi. Une fuite de mémoire se produit lorsque votre programme boucle sur une section de code, et que ce code alloue du segment de mémoire, puis "en perd la trace" sans le libérer.
En fait, il n'est pas nécessaire d'appeler free () ou de supprimer juste avant de quitter. Lorsque le processus se termine, toute sa mémoire est récupérée par le système d'exploitation (c'est certainement le cas avec POSIX. Sur d'autres systèmes d'exploitation - en particulier ceux intégrés - YMMV).
La seule prudence que j'aurais à ne pas libérer de la mémoire au moment de la sortie est que si jamais vous refactorisez votre programme pour qu'il devienne, par exemple, un service qui attend l'entrée, fait tout ce que fait votre programme, puis boucle pour attendre un autre appel de service, alors ce que vous avez codé peut se transformer en une fuite de mémoire.
la source
ceci est si spécifique au domaine qu'il ne vaut guère la peine d'y répondre. utilisez votre tête flippante.
et il existe un éventail de situations intermédiaires.
le coût d'opportunité ($$$) de retarder la sortie d'un produit pour corriger toutes les fuites de mémoire, sauf les pires, est généralement inférieur à tout sentiment d'être «bâclé ou non professionnel». Votre patron vous paie pour lui faire de l'argent, pas pour avoir des sentiments chaleureux et flous.
la source
Vous devez d'abord réaliser qu'il y a une grande différence entre une fuite de mémoire perçue et une fuite de mémoire réelle. Très fréquemment, les outils d'analyse signalent de nombreux harengs rouges et étiquettent quelque chose comme ayant été divulgué (mémoire ou ressources telles que des poignées, etc.) là où il ne l'est pas réellement. Cela est souvent dû à l'architecture de l'outil d'analyse. Par exemple, certains outils d'analyse signalent les objets d'exécution comme des fuites de mémoire car ils ne voient jamais ces objets libérés. Mais la désallocation se produit dans le code d'arrêt de l'exécution, que l'outil d'analyse peut ne pas voir.
Cela dit, il y aura toujours des moments où vous aurez des fuites de mémoire réelles qui sont soit très difficiles à trouver, soit très difficiles à réparer. Alors maintenant, la question devient: est-il jamais OK de les laisser dans le code?
La réponse idéale est «non, jamais». Une réponse plus pragmatique pourrait être «non, presque jamais». Très souvent dans la vraie vie, vous avez un nombre limité de ressources et de temps pour résoudre et une liste interminable de tâches. Lorsque l'une des tâches consiste à éliminer les fuites de mémoire, la loi des rendements décroissants entre très souvent en jeu. Vous pourriez éliminer disons 98% de toutes les fuites de mémoire dans une application en une semaine, mais les 2% restants pourraient prendre des mois. Dans certains cas, il peut même être impossible d'éliminer certaines fuites en raison de l'architecture de l'application sans refactorisation majeure du code. Vous devez peser les coûts et les avantages de l'élimination des 2% restants.
la source
Dans ce genre de question, le contexte est tout. Personnellement, je ne supporte pas les fuites, et dans mon code, je m'efforce de les réparer si elles surviennent, mais cela ne vaut pas toujours la peine de réparer une fuite, et quand les gens me paient à l'heure que j'ai à l'occasion leur a dit que cela ne valait pas la peine pour moi de réparer une fuite dans leur code. Laisse moi te donner un exemple:
Je triais un projet, faisais du travail de perf et corrigeais beaucoup de bugs. Il y a eu une fuite lors de l'initialisation des applications que j'ai traquée et parfaitement comprise. Le réparer correctement aurait nécessité une journée ou deux de refactorisation d'un morceau de code par ailleurs fonctionnel. J'aurais pu faire quelque chose de hacky (comme bourrer la valeur dans un global et l'attraper à un moment donné, je sais que ce n'était plus utilisé pour la libérer), mais cela aurait juste causé plus de confusion au gars suivant qui devait toucher le code.
Personnellement, je n'aurais pas écrit le code de cette façon en premier lieu, mais la plupart d'entre nous ne travaillons pas toujours sur des bases de code parfaitement conçues, et parfois vous devez regarder ces choses avec pragmatisme. Le temps qu'il m'aurait fallu pour corriger cette fuite de 150 octets pourrait plutôt être consacré à des améliorations algorithmiques qui ont réduit les mégaoctets de RAM.
En fin de compte, j'ai décidé que la fuite de 150 octets pour une application qui utilisait un gig de RAM et fonctionnait sur une machine dédiée ne valait pas la peine de le réparer, alors j'ai écrit un commentaire disant qu'il avait été divulgué, ce qui devait être changé pour réparer et pourquoi cela n'en valait pas la peine à l'époque.
la source
Alors que la plupart des réponses se concentrent sur de vraies fuites de mémoire (qui ne sont jamais correctes, car elles sont un signe de codage bâclé), cette partie de la question me semble plus intéressante:
Si la mémoire associée est utilisée, vous ne pouvez pas la libérer avant la fin du programme. Que la libération soit effectuée par la sortie du programme ou par le système d'exploitation n'a pas d'importance. Tant que cela est documenté, afin que le changement n'introduise pas de véritables fuites de mémoire, et tant qu'il n'y a pas de destructeur C ++ ou de fonction de nettoyage C impliqué dans l'image. Un fichier non fermé peut être révélé par une fuite
FILE
objet , mais un fclose () manquant peut également empêcher le vidage du tampon.Donc, revenons au cas d'origine, c'est à mon humble avis parfaitement OK en soi, à tel point que Valgrind, l'un des détecteurs de fuite les plus puissants, ne traitera ces fuites que sur demande. Sur Valgrind, lorsque vous écrasez un pointeur sans le libérer au préalable, il est considéré comme une fuite de mémoire, car il est plus susceptible de se reproduire et de provoquer une croissance infinie du tas.
Ensuite, il n'y a pas de blocs de mémoire nfreed qui sont toujours accessibles. On pourrait s'assurer de les libérer tous à la sortie, mais ce n'est qu'une perte de temps en soi. Le fait est de savoir s'ils pouvaient être libérés avant . La réduction de la consommation de mémoire est utile dans tous les cas.
la source
Je suis d'accord avec vfilby - cela dépend. Sous Windows, nous traitons les fuites de mémoire comme des bogues relativement graves. Mais cela dépend beaucoup du composant.
Par exemple, les fuites de mémoire ne sont pas très graves pour les composants qui s'exécutent rarement et pour des périodes de temps limitées. Ces composants s'exécutent, font leur travail, puis quittent. Quand ils sortent, toute leur mémoire est libérée implicitement.
Cependant, les fuites de mémoire dans les services ou d'autres composants à long terme (comme le shell) sont très graves. La raison en est que ces bogues «volent» la mémoire au fil du temps. La seule façon de récupérer cela est de redémarrer les composants. La plupart des gens ne savent pas comment redémarrer un service ou le shell - donc si les performances de leur système souffrent, ils redémarrent simplement.
Donc, si vous avez une fuite - évaluez son impact de deux manières
Foredecker
la source
Même si vous êtes sûr que votre fuite de mémoire «connue» ne causera pas de ravages, ne le faites pas. Au mieux, cela vous permettra de faire une erreur similaire et probablement plus critique à un moment et à un endroit différents.
Pour moi, demander c'est comme poser la question "Puis-je briser le feu rouge à 3 heures du matin quand personne n'est là?". Bien sûr, cela ne causera peut-être aucun problème à ce moment-là, mais cela vous fournira un levier pour faire de même aux heures de pointe!
la source
Non, vous ne devriez pas avoir de fuites que le système d'exploitation nettoiera pour vous. La raison (non mentionnée dans les réponses ci-dessus pour autant que je puisse vérifier) est que vous ne savez jamais quand votre main () sera réutilisé en tant que fonction / module dans un autre programme . Si votre main () devient une fonction fréquemment appelée dans le logiciel d'une autre personne - ce logiciel aura une fuite de mémoire qui mange de la mémoire au fil du temps.
KIV
la source
Je suppose que c'est bien si vous écrivez un programme destiné à fuir la mémoire (c'est-à-dire pour tester l'impact des fuites de mémoire sur les performances du système).
la source
Je suis surpris de voir autant de définitions incorrectes de ce qu'est réellement une fuite de mémoire. Sans définition concrète, une discussion pour savoir si c'est une mauvaise chose ou non n'ira nulle part.
Comme certains commentateurs l'ont souligné à juste titre, une fuite de mémoire ne se produit que lorsque la mémoire allouée par un processus sort du domaine d'application dans la mesure où le processus n'est plus en mesure de le référencer ou de le supprimer.
Un processus qui accapare de plus en plus de mémoire ne fuit pas nécessairement. Tant qu'il est capable de référencer et de désallouer cette mémoire, elle reste sous le contrôle explicite du processus et n'a pas fuité. Le processus est peut-être mal conçu, surtout dans le contexte d'un système où la mémoire est limitée, mais ce n'est pas la même chose qu'une fuite. Inversement, la perte de portée, par exemple, d'un tampon de 32 octets est toujours une fuite, même si la quantité de mémoire divulguée est faible. Si vous pensez que cela est insignifiant, attendez que quelqu'un enveloppe un algorithme autour de votre appel de bibliothèque et l'appelle 10 000 fois.
Je ne vois aucune raison pour autoriser les fuites dans votre propre code, aussi petit soit-il. Les langages de programmation modernes tels que C et C ++ se donnent beaucoup de mal pour aider les programmeurs à prévenir de telles fuites et il y a rarement un bon argument pour ne pas adopter de bonnes techniques de programmation - en particulier lorsqu'elles sont couplées à des fonctionnalités de langage spécifiques - pour éviter les fuites.
En ce qui concerne le code existant ou tiers, où votre contrôle sur la qualité ou la capacité d'apporter une modification peut être très limité, en fonction de la gravité de la fuite, vous pouvez être obligé d'accepter ou de prendre des mesures d'atténuation telles que le redémarrage régulier de votre processus pour réduire l'effet de la fuite.
Il peut ne pas être possible de modifier ou de remplacer le code existant (qui fuit), et vous pouvez donc être tenu de l'accepter. Cependant, ce n'est pas la même chose que de déclarer que c'est OK.
la source
Ce n'est vraiment pas une fuite si c'est intentionnel et ce n'est pas un problème, sauf si c'est une quantité importante de mémoire, ou pourrait devenir une quantité importante de mémoire. Il est assez courant de ne pas nettoyer les allocations globales pendant la durée de vie d'un programme. Si la fuite se trouve dans un serveur ou une application longue, augmente avec le temps, alors c'est un problème.
la source
Je pense que vous avez répondu à votre propre question. Le plus gros inconvénient est la façon dont ils interfèrent avec les outils de détection de fuite de mémoire, mais je pense que cet inconvénient est un énorme inconvénient pour certains types d'applications.
Je travaille avec des applications serveur héritées qui sont censées être solides, mais elles ont des fuites et les globaux gênent les outils de détection de mémoire. C'est un gros problème.
Dans le livre "Collapse" de Jared Diamond, l'auteur se demande à quoi pensait le gars qui a abattu le dernier arbre de l'île de Pâques, l'arbre dont il aurait eu besoin pour construire un canoë pour quitter l'île. Je me pose des questions sur le jour il y a de nombreuses années où cette première mondiale a été ajoutée à notre base de code. C'était le jour où il aurait dû être attrapé.
la source
Je vois le même problème que toutes les questions de scénario comme celle-ci: que se passe-t-il lorsque le programme change, et soudain, cette petite fuite de mémoire est appelée dix millions de fois et la fin de votre programme est à un endroit différent, donc cela a-t-il de l'importance? Si c'est dans une bibliothèque, enregistrez un bogue avec les responsables de la bibliothèque, ne mettez pas de fuite dans votre propre code.
la source
Je réponds non.
En théorie, le système d'exploitation se nettoiera après vous si vous laissez un gâchis (maintenant c'est juste impoli, mais comme les ordinateurs n'ont pas de sentiments, cela pourrait être acceptable). Mais vous ne pouvez pas prévoir toutes les situations possibles qui pourraient se produire lorsque votre programme est exécuté. Par conséquent (à moins que vous ne puissiez effectuer une preuve formelle d'un certain comportement), la création de fuites de mémoire est simplement irresponsable et bâclée d'un point de vue professionnel.
Si un composant tiers fuit de la mémoire, c'est un argument très fort contre son utilisation, non seulement en raison de l'effet imminent, mais aussi parce qu'il montre que les programmeurs fonctionnent de manière bâclée et que cela peut également avoir un impact sur d'autres mesures. Maintenant, lorsque l'on considère les systèmes hérités, c'est difficile (pensez aux composants de navigation Web: à ma connaissance, ils fuient tous la mémoire) mais cela devrait être la norme.
la source
Historiquement, cela comptait sur certains systèmes d'exploitation dans certains cas extrêmes. Ces cas marginaux pourraient exister à l'avenir.
Voici un exemple, sur SunOS à l'ère Sun 3, il y avait un problème si un processus utilisait exec (ou plus traditionnellement fork puis exec), le nouveau processus suivant hériterait de la même empreinte mémoire que le parent et il ne pourrait pas être réduit . Si un processus parent allouait 1/2 gig de mémoire et ne le libérait pas avant d'appeler exec, le processus enfant commencerait à utiliser ce même 1/2 gig (même s'il n'était pas alloué). Ce comportement était mieux présenté par SunTools (leur système de fenêtrage par défaut), qui était un porc de mémoire. Chaque application créée a été créée via fork / exec et a hérité de l'empreinte SunTools, remplissant rapidement l'espace de swap.
la source
Cela a déjà été discuté ad nauseam . L'essentiel est qu'une fuite de mémoire est un bogue et doit être corrigé. Si une bibliothèque tierce fuit de la mémoire, on peut se demander ce qui ne va pas, non? Si vous construisiez une voiture, utiliseriez-vous un moteur qui fuit parfois de l'huile? Après tout, quelqu'un d'autre a fabriqué le moteur, ce n'est donc pas de votre faute et vous ne pouvez pas le réparer, non?
la source
En règle générale, une fuite de mémoire dans une application autonome n'est pas fatale, car elle est nettoyée à la fermeture du programme.
Que faites-vous pour les programmes serveur conçus pour ne pas quitter?
Si vous êtes le genre de programmeur qui ne conçoit pas et n'implémente pas de code où les ressources sont allouées et libérées correctement, alors je ne veux rien avoir à faire avec vous ou votre code. Si vous ne vous souciez pas de nettoyer votre mémoire qui a fui, qu'en est-il de vos serrures? Les laissez-vous traîner là aussi? Laissez-vous de petits morceaux de fichiers temporaires dans divers répertoires?
Vous perdez cette mémoire et laissez le programme la nettoyer? Non, absolument pas. C'est une mauvaise habitude, qui conduit à des bugs, des bugs et plus de bugs.
Nettoyez-vous après vous-même. Yo maman ne travaille plus ici.
la source
En règle générale, si vous avez des fuites de mémoire que vous sentez que vous ne pouvez pas éviter, vous devez réfléchir davantage à la propriété des objets.
Mais à votre question, ma réponse en un mot est Dans le code de production, oui. Pendant le développement, non . Cela peut sembler à l'envers, mais voici mon raisonnement:
Dans la situation que vous décrivez, où la mémoire est conservée jusqu'à la fin du programme, il est parfaitement normal de ne pas la libérer. Une fois votre processus terminé, le système d'exploitation sera de toute façon nettoyé. En fait, cela pourrait améliorer l'expérience de l'utilisateur: dans un jeu sur lequel j'ai travaillé, les programmeurs pensaient qu'il serait plus propre de libérer toute la mémoire avant de quitter, provoquant l'arrêt du programme jusqu'à une demi-minute! Un changement rapide qui vient d'appeler exit () a plutôt fait disparaître immédiatement le processus et remis l'utilisateur sur le bureau où il voulait être.
Cependant, vous avez raison au sujet des outils de débogage: ils feront écho, et tous les faux positifs pourraient rendre difficile la découverte de vos fuites de mémoire réelles. Et à cause de cela, écrivez toujours du code de débogage qui libère la mémoire et désactivez-le lorsque vous expédiez.
la source