238 votes

Sont des fuites de mémoire, jamais ok?

Est-il jamais possible d'avoir une fuite de mémoire dans votre application C ou C++?

Que faire si vous allouer de la mémoire et de l'utiliser jusqu'à la dernière ligne de code dans votre application (par exemple, un objet global du destructeur)? Aussi longtemps que la consommation de mémoire de ne pas grandir au fil du temps, c'est bon pour la confiance de l'OS pour libérer votre mémoire pour vous lorsque votre application se termine (sur Windows, Mac et Linux)? Voudriez-vous même considérer cela comme un véritable fuite de mémoire si la mémoire a été utilisé en continu jusqu'à ce qu'il a été libéré par l'OS.

Que faire si un tiers de la bibliothèque forcé de cette situation sur vous? Refuserait d'utiliser cette troisième partie de la bibliothèque de n'importe quelle grande il pourrait être autrement?

Je ne vois qu'un inconvénient, c'est que ces fuites sans gravité s'affiche avec la mémoire de la fuite des outils de détection des faux positifs.

341voto

JohnMcG Points 5062

Pas de.

En tant que professionnels, nous ne devrions pas nous poser la question, "Est-il toujours OK pour ce faire?" mais plutôt "Est-il toujours une bonne raison de faire cela?" Et "la chasse que la fuite de mémoire est une douleur" n'est pas une bonne raison.

Je tiens à garder les choses simples. Et la règle est simple, c'est que mon programme devrait pas avoir des fuites de mémoire.

Qui me rend la vie simple, trop. Si je détecte une fuite de mémoire, j'ai l'éliminer, plutôt que de courir à travers quelques élaborer arbre de décision de la structure pour déterminer si elle est "acceptable" fuite de mémoire.

Il est semblable à des avertissements du compilateur – sera l'avertissement être fatale à ma demande en particulier? Peut-être pas.

Mais au final c'est une question de discipline professionnelle. Tolérer les avertissements du compilateur et de tolérer des fuites de mémoire est une mauvaise habitude qui finira par me mordre à l'arrière.

À prendre les choses à l'extrême, serait-il jamais être acceptable pour un chirurgien de laisser un morceau de matériel d'exploitation à l'intérieur d'un patient?

Bien qu'il soit possible qu'une circonstance pourrait survenir en cas de coût/risque de suppression de cette pièce d'équipement dépasse le coût/risque de le laisser dans, et il pourrait y avoir des circonstances où il était inoffensif, si j'ai vu cette question posté sur SurgeonOverflow.com et vu toute réponse autre que "non", il porterait gravement atteinte à ma confiance dans la profession médicale.

Si un tiers de la bibliothèque forcé cette situation sur moi, il me conduirait à soupçonnez la qualité globale de la bibliothèque en question. Ce serait comme si je test conduit une voiture et trouvé un couple lâche les rondelles et les écrous dans l'une des porte – gobelets- il peut ne pas être un gros problème en soi, mais il trahit un manque d'engagement à la qualité, donc, je voudrais envisager des solutions de rechange.

83voto

Jim C Points 4736

Je ne considère pas ça être une fuite de mémoire, à moins que la quantité de mémoire utilisée "ne cesse de croître. Ayant quelques inédits de la mémoire, tout n'est pas idéal, n'est pas un gros problème, sauf si la quantité de mémoire requise ne cesse de croître.

80voto

Charlie Martin Points 62306

Let's get nos définitions correctes, d'abord. Un mémoire de fuite , c'est quand la mémoire est allouée dynamiquement, par exemple, avec malloc(), et toutes les références à la mémoire sont perdus sans gratuit. Un moyen facile de le faire est comme ceci:

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

Notez qu'à chaque fois autour de l'while(1) de la boucle, 1024 (+frais généraux) octets sont affectées, et la nouvelle adresse attribuée à vp; il n'y a pas d'autres pointeur de la précédente malloc ed blocs. Ce programme s'exécute jusqu'à ce que le tas s'épuise, et il n'y a aucun moyen de récupérer le malloc ed mémoire. La mémoire est une "fuite" de sortir de la masse, de ne jamais être vu à nouveau.

Ce que vous décrivez, même si, comme son

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

Vous allouer de la mémoire, de travailler avec elle jusqu'à ce que le programme se termine. Ce n'est pas une fuite de mémoire; il ne réduit en rien le programme, et toute la mémoire sera balayé en place automatiquement lorsque le programme se termine.

En général, vous devriez éviter les fuites de mémoire. D'abord, parce que, comme l'altitude au-dessus de vous et de carburant de retour au hangar, de la mémoire qui a coulé et ne peuvent pas être récupérés est inutile; la seconde, c'est beaucoup plus facile de coder correctement, pas de fuite de mémoire, au début qu'il s'agit de trouver une fuite de mémoire plus tard.

41voto

vfilby Points 5975

En théorie non, en pratique, ça dépend.

Cela dépend vraiment de la quantité de données du programme de travail, à quelle fréquence le programme est exécuté et si oui ou non il est constamment en cours d'exécution.

Si j'ai un rapide programme qui lit une petite quantité de données, de calcul et de sorties, une petite fuite de mémoire ne sera jamais remarqué. Parce que le programme ne fonctionne pas pour très longtemps et n'en utilise qu'une petite quantité de mémoire, la fuite sera de petite taille et libéré lorsque le programme existe.

D'autre part, si j'ai un programme qui traite des millions de documents et pistes pour une longue période de temps, une petite fuite de mémoire peut faire tomber la machine donné assez de temps.

Comme pour les bibliothèques tierces qui ont des fuites, s'ils causent un problème soit corrigé de la bibliothèque ou de trouver une meilleure solution. Si cela ne cause pas un problème, est-il vraiment important?

37voto

Artelius Points 25772

Beaucoup de gens semblent être sous l'impression qu'une fois que vous libérer de la mémoire, il est immédiatement renvoyé au système d'exploitation et peut être utilisé par d'autres programmes.

Ce n'est pas vrai. Les systèmes d'exploitation couramment gérer la mémoire dans 4KiB pages. malloc , et d'autres sortes de la gestion de la mémoire d'obtenir des pages de l'OS et de la sous-gérer comme ils l'entendent. Il est fort probable qu' free() va pas retourner les pages vers le système d'exploitation, sous l'hypothèse que votre programme va malloc plus de mémoire plus tard.

Je ne dis pas qu' free() ne retourne jamais de la mémoire pour le système d'exploitation. Il peut arriver, surtout si vous êtes en libérant de grandes étendues de mémoire. Mais il n'y a aucune garantie.

Le fait important: Si vous n'avez pas de mémoire libre que vous n'avez plus besoin, d'autres mallocs sont garantis à consommer encore plus de mémoire. Mais si vous libérez d'abord, malloc peut 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 n'est pas va nécessiter plus de mémoire à partir de maintenant (par exemple, il est dans la phase de nettoyage), la libération de la mémoire n'est pas si important. Cependant, si le programme peut allouer plus de mémoire, plus tard, vous devriez éviter les fuites de mémoire - en particulier celles qui peuvent se produire à plusieurs reprises.

Voir également de ce commentaire pour plus de détails sur le pourquoi de la libération de la mémoire juste avant la résiliation est mauvais.

Un intervenant n'a pas l'air de comprendre que l'appelant free() ne met pas automatiquement à permettre à d'autres programmes de l'utilisation de la mémoire libérée. Mais c'est le but de cette réponse!

Donc, pour convaincre les gens, je vais vous montrer un exemple où free() ne fait que très peu de bien. Pour faire le calcul est facile à suivre, je vais faire semblant que le système d'exploitation gère la mémoire de 4000 octets pages.

Supposons que vous allouer de dix mille (100 octets blocs (pour des raisons de simplicité, je vais ignorer la mémoire supplémentaire qui serait nécessaire pour gérer ces allocations). Ce qui consomme de 1 MO, ou de 250 pages. Si vous puis gratuit 9000 de ces blocs au hasard, vous êtes de gauche avec juste 1000 blocs - mais ils sont dispersés un peu partout. Statistiquement, environ 5 des pages sera vide. Les autres 245 auront chacune au moins un bloc alloué. Ce qui revient à 980KB de mémoire, cela ne peut pas être récupérée par le système d'exploitation, même si désormais vous n'100KB affectés!

D'autre part, vous pouvez maintenant malloc() 9000 blocs de plus sans augmenter la quantité de mémoire de votre programme est attachant.

Même lorsqu' free() pourrait techniquement retour de la mémoire à l'OS, il ne peut pas le faire. free() des besoins de parvenir à un équilibre entre exploitation rapidement et d'économiser la mémoire. Et d'ailleurs, un programme qui a déjà alloué beaucoup de mémoire, puis libéré, il est susceptible de le faire à nouveau. Un serveur web a besoin de gérer la demande après demande après demande - il est logique de garder du "mou" de la mémoire disponible de sorte que vous n'avez pas besoin de demander au système d'exploitation pour la mémoire de tous les temps.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X