Joa*_*nge 54 .net c# garbage-collection memory-leaks managed
当您确保所有句柄,实现的东西IDispose都被丢弃时,在托管系统中是否有可能泄漏内存?
是否会出现遗漏某些变量的情况?
Ree*_*sey 63
事件处理程序是非显而易见的内存泄漏的常见来源.如果你从object2订阅了object1上的一个事件,那么就执行object2.Dispose()并假装它不存在(并从你的代码中删除所有引用),在object1的事件中有一个隐式引用会阻止object2被垃圾收集.
MyType object2 = new MyType();
// ...
object1.SomeEvent += object2.myEventHandler;
// ...
// Should call this
// object1.SomeEvent -= object2.myEventHandler;
object2.Dispose();
Run Code Online (Sandbox Code Playgroud)
这是泄漏的常见情况 - 忘记轻松取消订阅事件.当然,如果收集了object1,也会收集object2,但直到那时才收集.
Mic*_*ows 40
我不认为C++风格的内存泄漏是可能的.垃圾收集器应该考虑到这些.即使永远不再使用对象,也可以创建聚合对象引用的静态对象.像这样的东西:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个明显愚蠢的例子,但它相当于托管运行时内存泄漏.
Rob*_*ney 27
正如其他人所指出的那样,只要内存管理器中没有实际的错误,不使用非托管资源的类就不会泄漏内存.
你在.NET中看到的不是内存泄漏,而是永远不会被丢弃的对象.只要垃圾收集器可以在对象图上找到它,就不会丢弃对象.因此,如果任何生物对象都有对象的引用,它就不会被处理掉.
事件注册是实现这一目标的好方法.如果一个对象注册了一个事件,那么它注册的任何事件都会引用它,即使你删除了对该对象的所有其他引用,直到它取消注册(或者它注册的对象变得无法访问)它将保持活跃状态.
因此,您必须在不知情的情况下注意注册静态事件的对象.ToolStrip例如,一个漂亮的功能是,如果您更改显示主题,它将自动在新主题中重新显示.它通过注册静态SystemEvents.UserPreferenceChanged事件来完成这个漂亮的功能.当您更改Windows主题时,会引发该事件,并且所有ToolStrip正在侦听该事件的对象都会收到有关新主题的通知.
好吧,假设你决定扔掉ToolStrip你的表格:
private void DiscardMyToolstrip()
{
Controls.Remove("MyToolStrip");
}
Run Code Online (Sandbox Code Playgroud)
你现在有一个ToolStrip永远不会死的.即使它不再出现在你的表单上,每次用户更改主题时,Windows都会尽职尽责地告诉ToolStrip它不存在.每次垃圾收集器运行时,它都会认为"我不能扔掉那个物体,UserPreferenceChanged事件正在使用它".
那不是内存泄漏.但它可能也是.
这样的事情使记忆探测器变得无价.运行一个内存分析器,你会说"这很奇怪,ToolStrip堆上似乎有一万个对象,即使我的表单上只有一个.这是怎么发生的?"
哦,如果你想知道为什么有些人认为财产制定者是邪恶的:ToolStrip要从UserPreferenceChanged事件中取消注册,请将其Visible属性设置为false.
Chr*_*ser 20
代表可能导致不直观的内存泄漏.
每当您从实例方法创建委托时,对该实例的引用都存储在该委托中.
此外,如果将多个委托组合成一个多播委托,那么只要在某处使用多播委托,就会有大量对大量对象的引用,这些对象不会被垃圾回收.
Zac*_*son 17
如果您正在开发一个WinForms应用程序,那么一个微妙的"泄漏" Control.AllowDrop属性(用于启用拖放).如果AllowDrop设置为"true",CLR仍将保留在您的控件上System.Windows.Forms.DropTarget.要解决此问题,请确保您Control的AllowDrop属性设置为false不再需要时,CLR将负责其余部分.
如前所述,保持参考将导致随着时间的推移增加内存使用.进入这种情况的一个简单方法是使用事件.如果你有一个长生命对象,其他对象听到的事件,如果从不删除监听器,那么长寿命对象上的事件将使这些其他实例在不再需要它们之后保持很长时间.
.NET应用程序中内存泄漏的唯一原因是,尽管它们的生命周期已经结束,但仍然会引用对象.因此,垃圾收集器无法收集它们.它们成为长寿的物体.
我发现,当对象的生命结束时,通过订阅事件而不取消订阅它很容易导致泄漏.