170 votes

Anatomie d’une « fuite de mémoire »

Dans .NET point de vue:

  • Qu'est ce qu'une Fuite de Mémoire?
  • Comment pouvez-vous déterminer si votre demande de fuites? Quels sont les effets?
  • Comment pouvez-vous éviter une fuite de mémoire?
  • Si votre application a fuite de mémoire, faut-il aller loin quand le processus s'arrête ou est tué? Ou faire des fuites de mémoire dans votre application affecter d'autres processus sur le système, même après l'achèvement du processus?
  • Et que dire de code non managé accessible via l'Interopérabilité COM et/ou de P/Invoke?

J'ai quelques réponses à ces questions moi-même, mais elles sont incomplètes. Qu'en pensez-vous?

110voto

Karl Seguin Points 10566

La meilleure explication que j'ai vu, c'est dans le Chapitre 7 de la libre Fondements de la Programmation ebook.

Pour l'essentiel, dans .NET une fuite de mémoire se produit lorsque les objets référencés sont enracinés, et par conséquent, ne peuvent être nettoyés. Cela se produit accidentellement, lorsque vous vous accrochez à des références au-delà de la portée souhaitée.

Vous saurez que vous avez des fuites lorsque vous commencez à recevoir outofmemoryexceptions ou de votre utilisation de la mémoire va au-delà de ce que vous attendez (perfmon a nice compteurs de mémoire).

La compréhension .NET la mémoire de modèle est votre meilleur moyen de l'éviter. Plus précisément, la compréhension de la façon dont le garbage collector fonctionne et comment les références de travail (encore une fois, je vous renvoie au chapitre 7 de l'ebook). Aussi, soyez conscient des écueils les plus courants, probablement le plus commun étant événements. Si l'objet inscrit à un événement sur un objet B, puis l'objet A va rester jusqu'à ce que l'objet B disparaît parce que B contient une référence à A. La solution est d'annuler l'inscription de votre événements lorsque vous avez terminé.

Bien sûr, un bon profil de la mémoire vous permettra de voir vos graphes d'objets et d'explorer l'imbrication/référencement de vos objets pour voir où les références sont en provenance et à ce que l'objet racine est responsable (rouge-porte de fourmis profil, JetBrains dotTrace, memprofiler sont vraiment bons choix, ou vous pouvez utiliser le texte-seulement windbg et sos, mais je recommanderais fortement commercial/visuels du produit, sauf si vous êtes un vrai gourou).

Je crois que le code non managé est soumis à typique des fuites de mémoire de unamanged code, sauf que les références partagées entre les deux sont gérés par le garbage collector. Peut-être tort sur ce dernier point.

35voto

Coincoin Points 12823

Strictement parlant, une fuite de mémoire est la consommation de la mémoire qui est "n'est plus utilisé" par le programme.

"Les plus utilisés" a plus d'un sens, on pourrait dire "pas plus de référence", qui est, totalement irrécupérable, ou cela pourrait signifier, référencé, récupérable, non utilisé, mais le programme conserve les références de toute façon. Seule la, plus tard, s'applique .Net pour parfaitement objets gérés. Cependant, pas toutes les classes sont parfait et à un moment donné, un sous-jacents non géré la mise en œuvre pourrait fuite ressources de façon permanente pour ce processus.

Dans tous les cas, l'application consomme plus de mémoire que ce qui est strictement nécessaire. Les côtés effets, en fonction de la quantité de fuite, peut aller de l'absence, de ralentissement causé par l'excès de la collection, à une série de mémoire exceptions et enfin une fatale erreur, suivi par la forcé l'arrêt du processus.

Vous savez qu'une application a un problème de mémoire lors de la surveillance montre que de plus en plus la mémoire est allouée à votre processus après chaque cycle de nettoyage de mémoire. Dans de tels cas, vous êtes soit de garder trop de mémoire, ou de certains sous-jacente non géré la mise en œuvre est en fuite.

Pour la plupart des fuites, les ressources sont récupérées lorsque le processus est terminé, cependant, certaines ressources ne sont pas toujours récupérés dans certains cas précis, GDI curseur poignées sont connus pour cela. Bien sûr, si vous avez un mécanisme de communication interprocessus, la mémoire allouée dans les autres processus ne serait pas libéré jusqu'à ce que le processus libère ou se termine.

32voto

Martin Points 3552

Je pense que le "qu'est ce qu'une fuite de mémoire" et "quels sont les effets" questions ont été répondues bien déjà, mais je voulais ajouter un peu plus de choses sur les autres questions...

Comment comprendre si les fuites de votre application

Une manière intéressante est d'ouvrir l'analyseur de performances et d'ajouter des traces pour les # octets dans tous les segments de mémoire et # Gen 2 collections , dans chaque cas, à la recherche juste à votre processus. Si l'exercice d'une fonction particulière causes le nombre total d'octets à augmenter, et que la mémoire reste affecté après la prochaine Gen 2 de la collection, on pourrait dire que la fonction de fuites de mémoire.

Comment prévenir

D'autres bonnes opinions ont été donnés. Je voudrais simplement ajouter que peut-être le plus souvent négligé de provoquer des .NET des fuites de mémoire est d'ajouter des gestionnaires d'événements pour les objets sans les enlever. Un gestionnaire d'événement associé à un objet est une forme de référence à cet objet, de sorte à empêcher la collecte, même après toutes les autres références ont disparu. Toujours n'oubliez pas de détacher les gestionnaires d'événements (à l'aide de l' -= de syntaxe en C#).

La fuite en aller quand le processus s'arrête, et ce sur COM interop?

Lors de votre processus s'arrête, toute la mémoire mappée dans l'espace d'adressage est récupérée par le système d'exploitation, y compris les objets COM servis à partir de la Dll. Relativement rarement, des objets COM peut être servi à partir de processus distincts. Dans ce cas, lors de votre processus de sorties, vous pouvez toujours être responsable de la mémoire allouée à un serveur COM les processus que vous avez utilisé.

19voto

John Points 9543

Je voudrais définir les fuites de mémoire comme un objet n'est pas de libérer la mémoire allouée fois qu'il a terminé. J'ai trouvé ceci peut se produire dans votre application si vous utilisez l'API de Windows et COM (c'est à dire le code non managé qui a un bug ou n'est pas géré correctement), dans le cadre et les composants tiers. J'ai aussi trouvé pas tiding vers le haut après l'utilisation de certains objets, comme les stylos peuvent causer le problème.

Personnellement, j'ai souffert de la Mémoire des Exceptions qui peuvent être causés, mais ne sont pas exclusifs à des fuites de mémoire en dot net applications. (OOM peut aussi venir de l'épinglage de voir l'Épinglage Artical). Si vous n'obtenez pas OOM erreurs ou besoin de confirmer si c'est une fuite de mémoire, elle provoque alors le seul moyen est de profil de votre application.

Je voudrais aussi essayer et vérifier les éléments suivants:

a) Tout ce qui implémente Idisposable est disposé soit à l'aide d'un bloc finally ou l'instruction à l'aide de ces comprennent les pinceaux, stylos, etc.(certaines personnes soutiennent de tout à rien en plus)

b)Tout ce qui a une méthode close est de nouveau fermé à l'aide de enfin ou l'instruction d'utilisation (bien que j'ai trouvé à l'aide ne sont pas toujours à proximité en fonction de si vous avez déclaré l'objet à l'extérieur de l'instruction à l'aide)

c)Si vous utilisez le code non managé/de l'API de windows que ces sujets sont traités correctement après. (certains ont des méthodes de nettoyage à libérer des ressources)

Espérons que cette aide.

19voto

Eric Z Beard Points 18473

Si vous avez besoin pour diagnostiquer une fuite de mémoire .NET, consultez ces liens:

http://msdn.microsoft.com/en-us/magazine/cc163833.aspx

http://msdn.microsoft.com/en-us/magazine/cc164138.aspx

Ces articles décrivent comment créer un vidage de la mémoire de votre processus et la façon de les analyser, de sorte que vous pouvez déterminer si votre fuite est géré ou non, et si elle est gérée, comment comprendre où il veut en venir.

Microsoft a également une version plus récente de l'outil afin d'aider avec la génération de crash dumps, pour remplacer ADPlus, appelé DebugDiag.

http://www.microsoft.com/downloads/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&displaylang=en

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