Est-il jamais possible dans un système géré de perdre de la mémoire lorsque vous vous assurez que toutes les poignées, les éléments qui implémentent IDispose
sont éliminés?
Y a-t-il des cas où certaines variables sont omises?
Est-il jamais possible dans un système géré de perdre de la mémoire lorsque vous vous assurez que toutes les poignées, les éléments qui implémentent IDispose
sont éliminés?
Y a-t-il des cas où certaines variables sont omises?
Les Gestionnaires d'événements sont une source courante de la non-évidence des fuites de mémoire. Si vous vous abonnez à un événement sur l'objet1 d'objet2, puis de faire de l'objet2.Dispose() et faire semblant qu'elle n'existe pas (et abandonner toutes les références à partir de votre code), il y a une référence implicite dans l'objet1 de l'événement qui permettra d'éviter objet2 d'être nettoyée.
MyType object2 = new MyType();
// ...
object1.SomeEvent += object2.myEventHandler;
// ...
// Should call this
// object1.SomeEvent -= object2.myEventHandler;
object2.Dispose();
C'est un cas courant de fuite - oublier de se désabonner facilement à partir d'événements. Bien sûr, si objet1 obtient recueillies, objet2 obtiendrez recueillies aussi bien, mais pas jusqu'alors.
Je ne pense pas que les fuites de mémoire de type C ++ soient possibles. Le ramasse-miettes devrait en tenir compte. Il est possible de créer un objet statique qui agrège les références même si les objets ne sont plus jamais utilisés. Quelque chose comme ça:
public static class SomethingFactory
{
private static List<Something> listOfSomethings = new List<Something>();
public static Something CreateSomething()
{
var something = new Something();
listOfSomethings.Add(something);
return something;
}
}
C'est un exemple évidemment stupide, mais ce serait l'équivalent d'une fuite de mémoire d'exécution gérée.
Comme d'autres l'ont souligné, tant qu'il n'y a pas un bug dans le gestionnaire de mémoire, les classes qui n'utilisent pas les ressources non managées ne sera pas une fuite de mémoire.
Ce que vous voyez dans .NET n'est pas de fuites de mémoire, mais des objets qui ne sont disposées. Un objet n'obtiendrez pas disposé aussi longtemps que le garbage collector peut trouver sur l'objet graphique. Donc, si tout objet vivant n'importe où est une référence à l'objet, il ne sera pas éliminé.
L'enregistrement d'un événement est un bon moyen pour ce faire. Si un objet s'inscrit à un événement, quel qu'il inscrit avec a une référence à elle, et même si vous éliminez toute autre référence à l'objet, jusqu'à ce qu'il annule l'inscription (ou de l'objet de l'enregistrement auprès devient inaccessible), il va rester en vie.
Donc, vous avez à regarder dehors pour les objets qui s'inscrivent pour les événements statiques sans votre connaissance. Une fonctionnalité utile de l' ToolStrip
, par exemple, est que si vous changez de thème d'affichage, il va automatiquement afficher de nouveau dans le nouveau thème. Il accomplit cette fonctionnalité utile en vous inscrivant à la statique SystemEvents.UserPreferenceChanged
événement. Lorsque vous changez votre thème Windows, l'événement est soulevé, et tous les de la ToolStrip
objets qui sont à l'écoute de l'événement notifié qu'il y a un nouveau thème.
Ok, supposons que vous décidez de jeter un ToolStrip
sur votre formulaire:
private void DiscardMyToolstrip()
{
Controls.Remove("MyToolStrip");
}
Vous avez maintenant une ToolStrip
qui ne mourra jamais. Même si elle n'est pas sur votre formulaire de plus, chaque fois que l'utilisateur modifie les thèmes de Windows seront consciencieusement dire le contraire inexistante) ToolStrip
environ. Chaque fois que le garbage collector s'exécute, il pense que "je ne peux pas jeter cet objet au loin, l' UserPreferenceChanged
événement est de les utiliser."
Ce n'est pas une fuite de mémoire. Mais il pourrait aussi bien être.
Des choses comme cela fait un profileur de mémoire inestimable. Exécuter un profileur de mémoire, et que vous allez dire "c'est étrange, il semble y avoir dix mille ToolStrip
objets sur le tas, même si il n'y a qu'un sur mon formulaire. Comment est-ce arrivé?"
Oh, et au cas où vous vous demandez pourquoi certaines personnes pensent que les setters de propriété sont mal: pour obtenir un ToolStrip
de se désinscrire de la UserPreferenceChanged
événement, définir son Visible
de la propriété d' false
.
Les délégués peuvent entraîner des fuites de mémoire non intuitives.
Chaque fois que vous créez un délégué à partir d'une méthode d'instance, une référence à cette instance est stockée "dans" ce délégué.
En outre, si vous combinez plusieurs délégués dans un délégué de multidiffusion, vous disposez d'un gros blob de références à de nombreux objets qui ne peuvent pas être récupérés tant que ce délégué de multidiffusion est utilisé quelque part.
Si vous développez une application WinForms, une "fuite" subtile est la propriété Control.AllowDrop
(utilisée pour activer le glisser-déposer). Si AllowDrop
est défini sur "true", le CLR conservera toujours votre contrôle malgré un System.Windows.Forms.DropTarget
. Pour résoudre ce problème, assurez-vous que votre propriété Control
's AllowDrop
est définie sur false
lorsque vous n'en avez plus besoin et le CLR se chargera du reste.
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.