Les fuites de mémoire sont-elles toujours correctes? [fermé]


231

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.


50
Si la consommation de mémoire n'augmente pas avec le temps, ce n'est pas une fuite.
mpez0

4
La plupart des applications (y compris tous les programmes .NET) ont au moins quelques tampons alloués une fois et jamais libérés explicitement. La définition de mpez0 est donc plus utile.
Ben Voigt du

2
Oui, si vous avez une mémoire infinie.
utilisateur

Une fuite "bénigne" (s'il y a une telle chose) n'est pas un faux positif - c'est une fuite qui a été très correctement détectée. La détection des fuites, même pour les fuites que vous n'avez pas envie de réparer, est la raison d'être d'un détecteur de fuites.
cHao

1
@ mpez0 "Si la consommation de mémoire n'augmente pas avec le temps, ce n'est pas une fuite"? Ce n'est pas la définition d'une fuite de mémoire. Une fuite est une mémoire qui a été divulguée, ce qui signifie qu'elle n'a pas été libérée et que vous n'y avez plus aucune référence, il vous est donc impossible de la libérer à nouveau. Qu'elle grandisse ou non n'a pas d'importance.
Mecki

Réponses:


329

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.


57
Vrai et pas vrai en même temps. En fin de compte, la plupart d'entre nous sont des esclaves salariés et tout désir de savoir-faire doit prendre le pas sur les exigences de l'entreprise. Si cette bibliothèque tierce a une fuite et économise 2 semaines de travail, il peut y avoir une analyse de rentabilisation pour l'utiliser, etc ...
Cervo

3
J'utiliserais la bibliothèque de toute façon, si c'était quelque chose dont j'avais besoin et qu'il n'y avait pas d'alternatives décentes, mais j'enregistrerais un bogue avec les responsables.
tloach

7
Bien que j'irais personnellement avec exactement la même réponse, il existe des programmes qui libèrent à peine la mémoire du tout. La raison en est qu'ils sont a) destinés à fonctionner sur des systèmes d'exploitation qui libèrent de la mémoire et b) conçus pour ne pas fonctionner très longtemps. Des contraintes rares pour un programme en effet, mais j'accepte cela comme parfaitement valable.

2
Pour ajouter quelques raisons pour une vérification précoce: lorsque vos outils de débogage sont inondés de fuites "bénignes", comment allez-vous trouver la "vraie"? Si vous ajoutez une fonction batch et que votre fuite de 1K / heure devient soudainement 1K / seconde?
peterchen

5
Hmm est "pas de fuite de mémoire" "parfait"?
JohnMcG

80

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.


12
Techniquement, une fuite est une mémoire allouée et toutes les références y relatives sont perdues. Ne pas désallouer la mémoire à la fin est juste paresseux.
Martin York

17
Si vous avez une fuite de mémoire unique de 4 Go, c'est un problème.
John Dibling

21
Peu importe si elle grandit ou non. D'autres programmes ne peuvent pas utiliser la mémoire si vous l'avez allouée.
Bill the Lizard

8
> D'autres programmes ne peuvent pas utiliser la mémoire si vous l'avez allouée. Eh bien, le système d'exploitation peut toujours échanger votre mémoire sur le disque et permettre à d'autres applications d'utiliser la RAM dont vous ne profitiez pas.
Max Lybbert

4
Si le programme est de courte durée, une fuite peut ne pas être si grave. De plus, bien qu'il ne soit PAS idéal, la pagination n'est pas aussi chère que certains le prétendent, car le programme n'est pas intéressé par cette mémoire (et ne sera donc pas échangé tout le temps) - sauf, bien sûr, si vous avez un GC ...
Arafangion

79

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:

#define BLK ((size_t)1024)
while(1){
    void * vp = malloc(BLK);
}

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 à

int main(){
    void * vp = malloc(LOTS);
    // Go do something useful
    return 0;
}

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.


Considérons maintenant quelques dizaines de ces allocations. Pensez maintenant à devoir déplacer le corps "principal" vers une routine qui est appelée plusieurs fois. Prendre plaisir. - Je suis d'accord avec le sentiment que ce n'est pas un si gros problème dans ce scénario, mais les scénarios changent. Comme on dit, écrivez toujours du code comme si le gars pour le maintenir sait où vous vivez.
peterchen

2
Eh bien, le fait est que la mémoire qui est mallocée et maintenue jusqu'à ce que le programme appelle _exit () ne soit pas "divulguée".
Charlie Martin

1
Il s'agit d'une fuite de mémoire et cela peut nuire à votre programme. Les allocations futures peuvent échouer à partir de ce processus car je suis sûr que vous vérifiez que malloc n'est pas retourné partout. en utilisant trop la mémoire, comme dans une situation imbriquée où le souvenir est rare, cela pourrait faire la différence entre la vie et la mort.
MikeJ

10
Mike, ce n'est tout simplement pas vrai. Dans un environnement C conforme, la fin de main libère toutes les ressources de processus. Dans un environnement intégré comme vous le décrivez, vous pourriez voir cette situation, mais vous n'auriez pas de main. Maintenant, je vais admettre qu'il pourrait y avoir des environnements imparfaits imparfaits pour lesquels cela ne serait pas vrai, mais j'ai vu des environnements imparfaits qui ne pouvaient pas gérer correctement + = aussi.
Charlie Martin

3
Oui, vous avez maintenant découvert que si vous avez malloctrop 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 une mallocmémoire d à laquelle la référence est perdue.
Charlie Martin

39

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?


Je ne sais pas si vous avez lu toute ma question ou non. Je dis que la mémoire est utilisée jusqu'à la fin de l'application. Elle ne grandit pas avec le temps. Le seul non non, c'est qu'il n'y a pas d'appel à libérer / supprimer.
Imbue

2
Ce n'est pas vraiment une fuite de mémoire. Une fuite de mémoire est une petite quantité de mémoire inutilisée mais non libérée, cette quantité augmente au fil du temps. Vous parlez d'une goutte de mémoire. Ne vous en préoccupez pas à moins que votre gouttelette ne soit très grosse.
vfilby

"Si cela ne pose pas de problème, est-ce vraiment important?" Non, ça n'a pas d'importance du tout. Je souhaite que plus de gens obtiennent cela au lieu de devenir religieux.
Imbue

2
@John: C'est généralement moins une question de développeurs paresseux et plus une question d'évolution des logiciels. Nous faisons tous des erreurs, les bugs sont notre métier; nous les faisons, nous les réparons, c'est ce que nous faisons. C'est toujours un équilibre entre les coûts initiaux et la maintenance à long terme, cet équilibre n'est jamais simple.
vfilby

1
John, je suis à 100% d'accord avec vous. Imbum La question est presque "combien acceptez-vous". Sloppy is sloppy .. Que diriez-vous de laisser une crevette derrière votre moniteur. puant est puant. Chaque fois que nous effondrons, notre industrie s'effondre un peu. Si vous savez qu'il y a une fuite et que vous savez que vous l'avez provoquée, vous devez la réparer.
baash05

37

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. mallocet 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 que free()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 techniquementfree() 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.


1
Et si d'autres programmes nécessitent la mémoire que votre programme contient inutilement, donc même si vous n'avez plus besoin de malloc, libérez () les espaces mémoire inutilisés :)
MN

2
Vous avez totalement manqué mon point. Lorsque vous libérez de la mémoire (), d'autres programmes ne peuvent pas l'utiliser !! (Parfois, ils le peuvent, en particulier si vous libérez de gros blocs de mémoire. Mais souvent, ils ne le peuvent pas!) Je vais modifier mon message pour rendre cela plus clair.
Artelius

27

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.


A propos des langages de script: Python utilise le recomptage mais dispose d'un GC uniquement pour libérer les références cycliques. Dans d'autres langues, le programmeur évite souvent complètement les références explicitement cycliques, ce qui crée d'autres problèmes.
Blaisorblade

Les versions antérieures de PHP ne libéraient pas de mémoire, elles fonctionnaient simplement du début à la fin, augmentant en mémoire - après les 0,1 secondes de temps d'exécution, le script se fermait et toute la mémoire était récupérée.
Arafangion

19

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 de free()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()et free(), 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ë.


J'adore l'idée d'habitude. Je suis également d'accord. Si je vois une fuite de mémoire, je me demande toujours dans quel autre coin le codeur a coupé. Surtout si c'est évident
baash05

C'est de loin la meilleure réponse. Je programme en C ++ depuis 5 ans maintenant et je n'ai jamais écrit une seule fuite de mémoire. La raison en est que je n'écris pas de code qui a tendance à fuir la mémoire. Une bonne conception C ++ vous a rarement utilisé new, ce qui élimine immédiatement la plupart des fuites de mémoire. Seulement si vous devez absolument l'utiliser new. Le résultat newdoit ê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 des shared_ptrcycles, auquel cas il faut savoir l'utiliser weak_ptr.
David Stone

15

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é.


3
"Mais vous devez absolument documenter que la fuite de mémoire est une décision consciente." Dieu merci. Le meilleur point fait jusqu'ici.
pestophage

15

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.


5
J'adore cette citation de Raymond Chen: "Le bâtiment est en train d'être démoli. Ne vous embêtez pas à balayer le sol et à vider les poubelles et à effacer les tableaux blancs. Et ne vous alignez pas à la sortie du bâtiment pour que tout le monde puisse y emménager / out to magnet. Tout ce que vous faites, c'est faire attendre l'équipe de démolition que vous ayez terminé ces tâches inutiles de ménage. " ( blogs.msdn.microsoft.com/oldnewthing/20120105-00/?p=8683 )
Andreas Magnusson

11

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.


C'est en fait un exemple de vieillissement des logiciels. Sujet fascinant d'étude.
Konrad Rudolph

Un redémarrage automatique de temps en temps, hein? La NASA, hein? (* regarde les anciens CD d'installation de Microsoft Windows *) Cela explique tellement de choses ...
Christian Severin

8

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.


Pas vraiment, car s'il n'est pas utilisé, il sera simplement paginé. Lorsque l'application se ferme, toute la mémoire est libérée.
Eclipse

Tant qu'il est alloué, les autres programmes ne pourront pas l'utiliser. Il ne sera pas paginé si vous ne le désallouez pas.
Bill the Lizard

Bien sûr, ce sera le cas - c'est à cela que sert la mémoire virtuelle. Vous pouvez avoir 1 Go de RAM réelle, et pourtant vous disposez de 4 processus allouant chacun 2 Go de mémoire virtuelle (tant que votre fichier d'échange est suffisamment volumineux).
Eclipse

Bien sûr, vous aurez des problèmes de pagination désagréables si chacun de ces processus utilise activement toute cette mémoire.
Eclipse

D'accord, je comprends de quoi vous parlez maintenant. Si vous libérez de la mémoire que vous n'utilisez pas, vous réduirez le besoin de pagination. Si vous le gardez alloué, votre application le gardera quand il sera paginé.
Bill the Lizard

8

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.


1
Vous pouvez utiliser des indicateurs de danger pour empêcher la fuite.
Demi

8

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.


Je ne suis pas d'accord. C'est « une fuite mémoire en soi ».
Konrad Rudolph

Ce n'est pas une fuite jusqu'à ce que vous "perdiez" la référence à l'objet. Vraisemblablement, si la mémoire est utilisée pendant la durée de vie du programme, elle n'est pas divulguée. Si la référence n'est pas perdue jusqu'à l'appel de exit (), ce n'est absolument pas une fuite.
nsayer

Amiga DOS a été le dernier O / SI examiné qui n'a pas nettoyé les processus. Cependant, sachez que la mémoire partagée IPC System V peut être conservée même si aucun processus ne l'utilise.
Jonathan Leffler

Palm ne libère pas de "fuite" de mémoire tant que vous n'avez pas synchronisé. c'est venu bien après l'amiga. J'ai exécuté des applications sur mon émulateur de paume qui avaient des fuites. Jamais elles n'ont fait leur chemin vers ma paume réelle.
baash05

6

ceci est si spécifique au domaine qu'il ne vaut guère la peine d'y répondre. utilisez votre tête flippante.

  • système d'exploitation de la navette spatiale: non, aucune fuite de mémoire autorisée
  • code de preuve de concept à développement rapide: réparer toutes ces fuites de mémoire est une perte de temps.

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.


2
Attitude très myope. Vous dites essentiellement qu'il n'est pas nécessaire d'utiliser des pratiques de programmation fondamentalement saines jusqu'à ce qu'un défaut soit constaté à cause de ces pratiques. Le problème est que les logiciels écrits à l'aide de méthodes bâclées ont tendance à avoir plus de défauts que les logiciels qui ne le sont pas.
John Dibling

1
Je ne crois pas tout ça. Et la gestion de la mémoire est plus compliquée que l'écriture de méthodes propres.
Dustin Getz

1
Dustin travaille évidemment dans le monde réel comme la plupart d'entre nous, où nous travaillons constamment contre des délais insensés pour suivre la concurrence. Le traitement des bogues doit donc être fait de manière pragmatique. En perdant trop de temps sur des bogues sans importance dans des programmes sans importance, vous ne ferez pas votre travail.
Wouter van Nifterick

Le problème avec cette attitude est: quand commencez-vous à réparer les fuites? "D'accord, c'est une centrale électrique, mais c'est juste du charbon, pas de l'uranium. Pourquoi réparer les fuites ici?" - J'ai appris dans le monde réel que si vous ne faites pas la bonne chose dès le début, tout le temps, cela n'arrive jamais. Cette attitude engendre des projets qui sont «achevés à 99%» après deux semaines et le restent pendant deux mois.
peterchen

5

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.


5

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.


Intelligent. D'autant plus que la fuite s'est produite lors de l'initialisation, ce qui signifie qu'elle ne s'accumulerait pas pendant l'exécution de l'application.
Demi

5

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:

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 déconstructeur 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.

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 fuiteFILE 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.


Wow ... quelqu'un qui sait ce qu'est une fuite de mémoire.
Simon Buchan

4

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

  1. À votre logiciel et à l'expérience de votre utilisateur.
  2. Au système (et à l'utilisateur) en termes de frugalité avec les ressources du système.
  3. Impact du correctif sur la maintenance et la fiabilité.
  4. Probabilité de provoquer une régression ailleurs.

Foredecker


3. Impact sur la maintenance du logiciel.
peterchen

3

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!


3

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


3

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).


3

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.


2

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.


2

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é.


2

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.


Dans ce cas, l'impact de la fuite de mémoire change et vous devez réévaluer la priorité de colmatage de la fuite.
John Dibling

@John: Vous feriez mieux de documenter au moins la fuite. Même alors, je ne ferais pas confiance à quelqu'un pour ne pas ignorer un gros commentaire clignotant rouge et copier-coller du code qui fuit de toute façon. Je préfère ne pas donner à quelqu'un la possibilité de le faire en premier lieu.
tloach

2

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.


2

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.


2

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?


Mais si vous possédez une voiture avec un moteur qui fuit de l'huile de temps en temps, dépensez-vous de l'argent pour le réparer, ou gardez-vous un œil sur les niveaux d'huile et faites le plein de temps en temps. La réponse dépend de toutes sortes de facteurs.
slim

Il ne s'agit pas de posséder une voiture. Il s'agit de construire une voiture. Si vous obtenez une bibliothèque tierce avec des fuites de mémoire et que vous devez absolument l'utiliser, vous vivez avec. Mais si vous êtes celui qui écrit un système ou une bibliothèque, il est de votre responsabilité de vous assurer qu'il est exempt de bogues.
Dima

+1 le traite comme n'importe quel autre bug. (Cela ne signifie pas «réparer instantanément» dans mon livre, mais «doit être corrigé» à coup sûr)
peterchen

2

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.


J'ai travaillé sur des programmes serveur qui utilisent délibérément des processus plutôt que des threads, de sorte que les fuites de mémoire et les erreurs de segmentation causent des dommages limités.
slim

Approche intéressante. Je serais un peu préoccupé par les processus qui ne parviennent pas à quitter et continuent à engloutir la mémoire.
EvilTeach

2

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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.