C# 内存泄漏问题

C# 内存泄漏问题,c#,garbage-collection,dispose,idisposable,C#,Garbage Collection,Dispose,Idisposable,自从我被要求修复一个存在内存泄漏问题的C#应用程序以来,我已经读了很多关于这方面的书,但我还没有找到这两个问题的答案: 考虑以下代码: private static ArrayList list = new ArrayList(); public void Function() { list.add(object1); list.add(object2); //didn't call clear() prior to reusing list

自从我被要求修复一个存在内存泄漏问题的C#应用程序以来,我已经读了很多关于这方面的书,但我还没有找到这两个问题的答案:

考虑以下代码:

   private static ArrayList list = new ArrayList();

   public void Function()
   {
     list.add(object1);
     list.add(object2);

     //didn't call clear() prior to reusing list
     list = new ArrayList();
   }
由于列表在创建新列表之前没有被清除,这会产生一些在静态列表本身被处理后不会被释放的垃圾吗

第二个问题是关于Form.Dispose()。我发现designer视图上的许多可用控件(即标签、图片框)都需要处理。似乎对窗体调用Dispose()会导致所有这些类型的控件也被释放(如果我错了,请纠正我),这很奇怪,因为设计器添加了一个重写的void Dispose(bool disposing)方法,而该方法不做这类事情。我假设这发生在基表单类的void Dispose(bool disposing)方法中

上面提到的问题是,我不太清楚我需要做什么来确保正确处理表单的所有资源。我不明白表单如何知道需要处理哪些对象。例如,如果在我的表单中有一个字段是自定义IDisposable对象,那么表单会知道它需要处理吗?或者我应该添加必要的代码来释放对象吗

另外,如果我确实需要添加代码来处理某些对象,那么如何处理设计器已经重写了void dispose(bool disposing)方法这一事实?我应该编辑设计器生成的代码,还是有更干净的方法


我希望这不会让人困惑,这有点难以解释。谢谢

不,那不是泄漏。当垃圾收集器搜索对象引用时,它将再也找不到对原始ArrayList的引用。你把它换了。因此,如果原始ArrayList对象及其所有元素也没有被引用,它将自动销毁这些元素

Form类知道如何处理自身以及作为该窗体上的子窗口的所有控件。当用户关闭表单时,Windows发送的WM_CLOSE消息会触发此代码。Controls集合帮助它找到所有子控件的引用,以便它也可以处理它们

但是,如果您自己从窗体中删除控件,则不会发生这种情况。现在由您对它们调用Dispose()。尤其是Controls.Clear()方法是危险的。不寻常的是,这会导致永久性泄漏,您拆除的控制装置通过“停车窗”保持活动。它使窗口句柄保持活动状态,以便您可以将其移动到其他位置,例如在另一个容器窗口上。如果你不移动它们,它们将永远驻留在停车窗口中。框架中没有其他类的行为是这样的


使用Taskmgr.exe的“进程”选项卡可以轻松诊断此泄漏。查看+选择列并勾选用户对象。如果在您的程序运行时该值稳步上升,则表明您正在泄漏控件。

静态arraylist的范围是什么。在我看来,它有一个窗体作用域。如果是,则不会处理它,因为静态对象始终被视为根对象,并且具有应用程序生命周期。根据我的经验,静力学总是占用更多的内存,并因此被提升到第2代。如果您有任何疑问,请使用.net内存分析器进行检查。您还可以获取内存转储并使用windbg进行分析,以找出泄漏的真正原因

在许多内存管理框架中,垃圾收集和其他方式,释放应用程序中的内存通常不会导致应用程序释放该内存,而是记录内存应可用于未来请求的事实。垃圾收集背后的部分思想是,当用户代码请求内存,而应用程序知道它至少有那么多立即可用的内存时,代码和应用程序都不会关心该请求不需要的内存是“已分配”还是“可用”。当对对象的最后一个可访问引用被破坏或变得不可访问时,该对象实际上就不存在了,但通常情况下,在满足分配请求或“每花一次释放内存”的比率与它可能得到的一样好

请注意,对于要回收与某个对象关联的内存的系统,绝对不能存在对该对象的任何类型的引用。如果存在对某个对象的任何可访问的弱引用,而该对象在其他情况下是不可访问的,则垃圾回收器必须使所有此类引用无效(因此它们不再标识该对象)在回收对象使用的空间之前。如果无法访问的对象具有已注册的终结器,则系统必须将该对象置于需要立即终结(从而使其不符合回收资格)的事物队列中,并注销终结器


当放弃对对象的所有其他引用时,GC会自动使弱引用和用于终结的引用无效,因此不会导致内存泄漏。但是,还有另一种引用可能会导致严重泄漏:来自比订阅者寿命更长的发布者的事件订阅。如果对象是subsc从对象B订阅事件,除非(1)对象A取消订阅事件,或(2)对象A不能被垃圾收集B本身就有资格进行垃圾收集。我发现自己很困惑,为什么Microsoft没有包括一些自动事件取消订阅的方法,但它们没有。谢谢,这是我需要了解的。我仍然不确定表单中没有包含的IDisposable对象。尽管如此,我猜我不得不这样做