我看到的是真正的内存泄漏吗?

isp*_*iro 3 .net c# winforms

我正在编写一个应用程序,在用户使用它之后 - 他可以"重置"它并再次使用它.实际使用会创建一些对象,包括控件.

我使用Process Explorer检查了内存使用情况并发现当使用应用程序时 - 内存使用量有所增加,但当应用程序"重置"时 - 内存使用率几乎没有下降.

因此,在'重置'我Dispose的所有Controls递归,甚至添加一个GC.Collect();启动.但Process Explorer -> (app's-) Properties -> .Net CLR Memory仍然显示堆上的很多东西和大量的内存使用.

这(必然)是内存泄漏吗?为什么强制GC没有帮助?

编辑:

我添加了GC.Collect();just for debugging - 用于确定是否存在泄漏.在GC工作之前,我并不担心"临时泄漏",我只是试图找出是否有对象永远不会超出范围(虽然我还没有找到它们)或者它只是一个问题时间,记忆将被收回.

Ed *_* S. 5

这(必然)是内存泄漏吗?

嗯......是的,不是.在C#应用程序中,大多数情况下都不可能有真正的内存泄漏,如果从未调用过Dispose(),即使是在引擎盖下使用本机资源的类型也会在终结器中清理它们.

无论如何,有可能有陈旧的引用和本机资源需要很长时间才能清理(或者写得不好的本机函数会泄漏自己),这与非托管语言中的真正内存泄漏具有相同的实际结果.

为什么强制GC没有帮助?

你给了GC一个建议,它选择不接受它.GC.Collect()不会强制GC清理所有内容,文档也会告诉您.其次,这个内存使用是否真的导致了问题?消耗了多少内存?它会被释放吗?如果它只是一小部分,那么你可能不用担心,让GC完成它的工作.

没有看到你的代码,我所能做的就是猜测.有几种方法可以在C#应用程序中建立内存压力.

  1. 陈旧的参考.列表中您从未清除的"死"对象的引用.事件处理程序也可以导致这种情况.例如,静态事件应始终取消订阅,因为事件委托包含对订阅者的引用.

    因此,如果订阅者超出范围而没有取消订阅该事件,则基本上存在内存泄漏,因为始终存在对这些"死"对象的有效引用.请注意,事件的典型用例不会导致这种情况发生,因为父(事件发布者)通常在您需要时超出范围.

  2. 不处理实现IDisposable的对象.当然,他们可能会在终结器中清理它们(所有.NET IDisposable类型都会这样做,其余的应该这样做),但终结器在不确定的时间运行,使整个事情变得不可预测.确保尽快调用Dispose()(using尽可能使用语句).

  3. 大对象堆碎片.如果要分配大量"大"对象(大于85,000字节的对象),则此段内存可能会碎片化.不会像在标准堆上分配的第0和第1代对象那样经常清理此内存.

.NET GC很复杂,通常非常擅长工作.有时候打电话是可以接受的GC.Collect,但你应该明白什么时候这是一个好主意,并且也意识到它可能会或者可能不会按照你的意愿行事.例如,如果您创建了大量短期对象.

当我用尽其他途径时,我有使用RedGate的.NET内存分析器的良好经验.我不是为他们工作,也不是我以任何方式与他们有关联,所以你知道,他们也有免费试用.值得一看.