59 votes

Pourquoi peut .NET pas de fuites de mémoire?

Ignorant le code unsafe, .NET ne peut pas avoir de fuites de mémoire. J'ai lu cela à l'infini dans de nombreux experts, et je le crois. Cependant, je ne comprends pas pourquoi il en est ainsi.

C'est ma compréhension que le cadre lui-même est écrit en C++ et C++ est sensible à des fuites de mémoire.

  • Le cadre sous-jacent tellement bien écrit, qu'il ne fait absolument pas toute possibilité d'une mémoire interne de fuites?
  • Est-il quelque chose dans le cadre du code qui s'auto-gère et même des solutions à ses propres serait-être des fuites de mémoire?
  • La réponse, c'est quelque chose que je n'ai pas pris en compte?

94voto

Oded Points 271275

.NET peut avoir des fuites de mémoire.

Pour la plupart, les gens parlent de le Garbage Collector, qui décide du moment où un objet (ou un ensemble d'objets de cycle) peut être obtenu en débarrasser. Cela évite le classique c et c++ style de fuites de mémoire, je veux dire de l'allocation de mémoire et de ne pas libérer plus tard.

Cependant, de nombreuses fois, les programmeurs ne se rendent pas compte que les objets ont encore pendants de références et ne sont pas des ordures, provoquant un... fuite de mémoire.

C'est normalement le cas lorsque les événements sont enregistrés (avec +=), mais pas non plus tard, mais aussi lors de l'accès à du code non managé (à l'aide de pInvokes ou des objets qui utilisent le système sous-jacent des ressources, telles que le système de fichiers ou de connexions de base de données) et de ne pas disposer correctement les ressources.

45voto

Joel Coehoorn Points 190579

Il y a déjà quelques bonnes réponses ici, mais je tiens à aborder un autre point. Nous allons examiner très attentivement à nouveau à votre question précise:


C'est ma compréhension que le cadre lui-même est écrit en C++ et C++ est sensible à des fuites de mémoire.

  • Le cadre sous-jacent tellement bien écrit, qu'il ne fait absolument pas toute possibilité d'une mémoire interne de fuites?
  • Est-il quelque chose dans le cadre du code qui s'auto-gère et même des solutions à ses propres serait-être des fuites de mémoire?
  • La réponse, c'est quelque chose que je n'ai pas pris en compte?

La clé ici est de faire la distinction entre votre code et leur code. L' .Net framework (et de Java, Allez, python et d'autres ordures collectées langues) vous promets que si vous comptez sur leur code, votre code ne sera pas une fuite de mémoire... au moins dans le sens traditionnel du terme. Vous pourriez vous retrouver dans des situations où certains objets ne sont pas libérés comme vous vous attendez, mais ces cas sont subtilement différent du traditionnel des fuites de mémoire, parce que les objets sont toujours joignable dans votre programme.

Vous êtes confus parce que vous avez bien comprendre que ce n'est pas la même chose que de dire n'importe quel programme que vous créez ne peut pas avoir une traditionnelle fuite de mémoire. Il pourrait encore être un bug dans leur code des fuites de mémoire.

Alors maintenant, vous avez à vous poser: préférez-vous faire confiance à votre code, ou leur code? Gardez à l'esprit que leur code n'est pas testé uniquement par les développeurs à l'origine (comme la vôtre, non?), c'est aussi aguerris de l'utilisation quotidienne par des milliers (peut-être des millions) d'autres développeurs comme vous. Tout d'importants problèmes de fuite de mémoire seraient parmi les premières choses identifiées et corrigées. Encore une fois, je ne dis pas qu'il n'est pas possible. C'est juste que c'est généralement une meilleure idée de la confiance de leur code qu'il est de votre propre... au moins à cet égard.

C'est donc la bonne réponse est ici que c'est une variante de votre première suggestion:

Le cadre sous-jacent tellement bien écrit, qu'il ne fait absolument pas toute possibilité d'une mémoire interne de fuites?

Il n'y a pas de possibilité, mais qu'il est beaucoup plus sûr que de le gérer vous-même. Je ne suis certainement pas au courant de tout connu des fuites dans le cadre.

15voto

Mitchel Sellers Points 38352

Après avoir examiné la documentation de Microsoft, en particulier "l'Identification des Fuites de Mémoire dans le CLR", Microsoft ne faire la déclaration que tant que vous n'êtes pas d'exécution de code non sécurisé au sein de votre application, qu'il n'est pas possible d'avoir une fuite de mémoire

Maintenant, ils soulignent également le concept de la perception d'une fuite de mémoire, ou comme il a été souligné dans les commentaires d'une "fuite des ressources", qui est l'utilisation d'un objet qui a des références persistantes et ne sont pas éliminés correctement. Cela peut se produire avec IO Objets, bases de données, éléments graphiques, et la comme. Ils sont ce que je généralement s'assimiler à une "fuite de mémoire" lorsque vous travaillez avec .NET, mais ils ne sont pas des fuites dans le sens traditionnel du terme.

12voto

Steven Sudit Points 13793

Grâce à la collecte des déchets, vous ne pouvez pas avoir régulièrement des fuites de mémoire (à part des cas particuliers, tels que le code unsafe et de P/Invoke). Cependant, vous pouvez certainement involontairement de conserver une référence en vie pour toujours, qui efficacement les fuites de mémoire.

modifier

Le meilleur exemple que j'ai vu jusqu'à présent d'une véritable fuite est le gestionnaire d'événement += erreur.

modifier

Voir ci-dessous pour une explication de l'erreur, et les conditions dans lesquelles il est considéré comme un véritable fuite en opposition à une quasi-véritable fuite.

4voto

Jeffrey L Whitledge Points 27574

Voici un exemple d'une fuite de mémoire .NET, ce qui n'implique pas de risque/pinvoke et n'a même pas impliquer les gestionnaires d'événements.

Supposons que vous écrivez un service d'arrière-plan qui reçoit une série de messages sur un réseau et des processus. Si vous créez une classe pour les tenir.

class Message 
{
  public Message(int id, string text) { MessageId = id; Text = text; }
  public int MessageId { get; private set; }
  public string Text { get; private set; }
}

OK, so far so good. Plus tard, vous vous rendez compte que certains exigence dans le système peut être plus facile si vous aviez une référence au message précédent disponibles lorsque vous effectuez le traitement. Il pourrait y avoir un certain nombre de raisons pour vouloir cela.

Si vous ajoutez une nouvelle propriété...

class Message
{
  ...
  public Message PreviousMessage { get; private set; }
  ...
}

Et d'écrire le code pour le régler. Et, bien sûr, quelque part dans la boucle principale, tu dois avoir une variable pour garder en place avec le dernier message:

  Message lastMessageReceived;

Ensuite, vous découvrirez quelques jours plus tard que votre service a bombardé, parce qu'il a rempli toute la mémoire disponible avec une longue chaîne de messages obsolètes.

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