4 回答
TA贡献1943条经验 获得超7个赞
事件处理程序是非常明显的内存泄漏的常见来源。如果您从object2订阅了object1上的事件,则执行object2.Dispose()并假装该事件不存在(并从代码中删除所有引用),则object1的事件中存在一个隐式引用,这将阻止object2被垃圾收集。
MyType object2 = new MyType();
// ...
object1.SomeEvent += object2.myEventHandler;
// ...
// Should call this
// object1.SomeEvent -= object2.myEventHandler;
object2.Dispose();
这是泄漏的常见情况-忘记轻松取消订阅事件。当然,如果收集了object1,则也将收集object2,但要到那时为止。
TA贡献1803条经验 获得超6个赞
我认为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;
}
}
那显然是一个愚蠢的例子,但这等同于托管运行时内存泄漏。
TA贡献1856条经验 获得超17个赞
正如其他人指出的那样,只要在内存管理器中没有实际的错误,不使用非托管资源的类就不会泄漏内存。
在.NET中看到的不是内存泄漏,而是永不处置的对象。只要垃圾收集器可以在对象图上找到对象,该对象就不会被处置。因此,如果任何活动对象在任何地方都具有对该对象的引用,则该对象不会被丢弃。
事件注册是实现此目标的好方法。如果一个对象注册了一个事件,则无论它注册了什么对象,都具有对该事件的引用,并且即使您消除了对该对象的所有其他引用,直到该对象取消注册(或与其注册的对象变得不可访问),它仍将保持活动状态。
因此,您必须注意在不知情的情况下注册静态事件的对象。ToolStrip例如,的一个漂亮功能是,如果您更改显示主题,它将自动在新主题中显示。它通过注册静态SystemEvents.UserPreferenceChanged事件来实现此精美功能。更改Windows主题时,将引发该事件,并且ToolStrip正在监听该事件的所有对象都将收到一个新主题的通知。
好的,假设您决定放弃ToolStrip表格上的:
private void DiscardMyToolstrip()
{
Controls.Remove("MyToolStrip");
}
您现在拥有一个ToolStrip永不消逝的世界。即使它不再存在于您的表单中,每次用户更改主题时,Windows都会忠实地告知ToolStrip有关此主题的信息。每当垃圾收集器运行时,它都会认为“我不能扔掉该对象,UserPreferenceChanged事件正在使用它。”
那不是内存泄漏。但也可能如此。
这样的事情使内存分析器变得无价。运行一个内存分析器,您会说:“很奇怪ToolStrip,即使我的表单上只有一个对象,堆上似乎有一万个对象。这是怎么发生的?”
哦,如果您想知道为什么有些人认为属性设置者是邪恶的:ToolStrip要从UserPreferenceChanged事件中取消注册,请将其Visible属性设置为false。
- 4 回答
- 0 关注
- 1080 浏览
添加回答
举报