猿问

C#中的内存泄漏

C#中的内存泄漏

当您确保所有句柄和实现的对象IDispose都已处置时,在受管系统中是否有可能泄漏内存?

在某些情况下会遗漏一些变量吗?


慕尼黑的夜晚无繁华
浏览 1081回答 4
4回答

杨__羊羊

事件处理程序是非常明显的内存泄漏的常见来源。如果您从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,但要到那时为止。

慕码人8056858

我认为C ++风格的内存泄漏是不可能的。垃圾收集器应解决这些问题。即使不再使用这些对象,也可以创建一个聚合对象引用的静态对象。像这样:public static class SomethingFactory{&nbsp; &nbsp; private static List<Something> listOfSomethings = new List<Something>();&nbsp; &nbsp; public static Something CreateSomething()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var something = new Something();&nbsp; &nbsp; &nbsp; &nbsp; listOfSomethings.Add(something);&nbsp; &nbsp; &nbsp; &nbsp; return something;&nbsp; &nbsp; }}那显然是一个愚蠢的例子,但这等同于托管运行时内存泄漏。

慕慕森

正如其他人指出的那样,只要在内存管理器中没有实际的错误,不使用非托管资源的类就不会泄漏内存。在.NET中看到的不是内存泄漏,而是永不处置的对象。只要垃圾收集器可以在对象图上找到对象,该对象就不会被处置。因此,如果任何活动对象在任何地方都具有对该对象的引用,则该对象不会被丢弃。事件注册是实现此目标的好方法。如果一个对象注册了一个事件,则无论它注册了什么对象,都具有对该事件的引用,并且即使您消除了对该对象的所有其他引用,直到该对象取消注册(或与其注册的对象变得不可访问),它仍将保持活动状态。因此,您必须注意在不知情的情况下注册静态事件的对象。ToolStrip例如,的一个漂亮功能是,如果您更改显示主题,它将自动在新主题中显示。它通过注册静态SystemEvents.UserPreferenceChanged事件来实现此精美功能。更改Windows主题时,将引发该事件,并且ToolStrip正在监听该事件的所有对象都将收到一个新主题的通知。好的,假设您决定放弃ToolStrip表格上的:private void DiscardMyToolstrip(){&nbsp; &nbsp; Controls.Remove("MyToolStrip");}您现在拥有一个ToolStrip永不消逝的世界。即使它不再存在于您的表单中,每次用户更改主题时,Windows都会忠实地告知ToolStrip有关此主题的信息。每当垃圾收集器运行时,它都会认为“我不能扔掉该对象,UserPreferenceChanged事件正在使用它。”那不是内存泄漏。但也可能如此。这样的事情使内存分析器变得无价。运行一个内存分析器,您会说:“很奇怪ToolStrip,即使我的表单上只有一个对象,堆上似乎有一万个对象。这是怎么发生的?”哦,如果您想知道为什么有些人认为属性设置者是邪恶的:ToolStrip要从UserPreferenceChanged事件中取消注册,请将其Visible属性设置为false。
随时随地看视频慕课网APP
我要回答