我写C ++ 10年。 我遇到的内存问题,但它们可以被固定的努力的合理费用。
在过去的几年中我一直在写C#。 我发现我仍然得到大量内存的问题。 他们是很难诊断和修复因非determinancy,因为C#的理念是,你不应该担心这样的事情,当你十分肯定地做。
我发现一个特别的问题是,我必须明确地配置和代码清理一切。 如果我不这样做,那么内存分析器真的不帮助,因为有这么多谷壳浮动你不能发现所有的数据内的泄漏,他们正试图告诉你。 我不知道如果我有错误的想法,或者如果我有工具是不是最好的。
什么样的策略和工具是在.NET解决内存泄漏有用吗?
Answer 1:
我用赛特的MemProfiler当我怀疑内存泄漏。
到目前为止,我发现它是非常可靠和强大。 它节省了至少有一次我的熏肉。
GC的工作相当不错,在.NET IMO,但就像任何其他语言或平台,如果你写不好的代码,不好的事情发生。
Answer 2:
只是为了遗忘到处置问题,请尝试在这篇博客文章中描述的解决方案 。 这里的精髓:
public void Dispose ()
{
// Dispose logic here ...
// It's a bad error if someone forgets to call Dispose,
// so in Debug builds, we put a finalizer in to detect
// the error. If Dispose is called, we suppress the
// finalizer.
#if DEBUG
GC.SuppressFinalize(this);
#endif
}
#if DEBUG
~TimedLock()
{
// If this finalizer runs, someone somewhere failed to
// call Dispose, which means we've failed to leave
// a monitor!
System.Diagnostics.Debug.Fail("Undisposed lock");
}
#endif
Answer 3:
我们使用蚂蚁探查专业在我们的项目中红门软件。 它可以很好地表现所有.NET语言基础的应用程序。
我们发现,.NET垃圾收集器在内存中的对象的清理很“安全”(因为它应该是)。 因为我们可能会在未来的某个时候使用它,它会保持周围只是对象。 这意味着我们需要更加小心,我们在内存充气对象的数量。 最后,我们转换我们的所有数据对象到一个“充气点播”为了减少开销,内存和提高性能(请求现场之前)。
编辑:这是我的意思通过进一步的解释“吹上的需求。” 在我们我们的数据库的对象模型中,我们使用父对象的属性,露出子对象(或多个)。 例如,如果我们有一些记录中引用的一到一个基础上,我们将构建像这样对其他一些“细节”或“查找”记载:
class ParentObject
Private mRelatedObject as New CRelatedObject
public Readonly property RelatedObject() as CRelatedObject
get
mRelatedObject.getWithID(RelatedObjectID)
return mRelatedObject
end get
end property
End class
我们发现,上述系统中创建一些真正的内存和性能问题时,有记忆了很多纪录。 因此,我们切换到时被要求他们的对象只充气系统和数据库呼叫,只进行必要的时候:
class ParentObject
Private mRelatedObject as CRelatedObject
Public ReadOnly Property RelatedObject() as CRelatedObject
Get
If mRelatedObject is Nothing
mRelatedObject = New CRelatedObject
End If
If mRelatedObject.isEmptyObject
mRelatedObject.getWithID(RelatedObjectID)
End If
return mRelatedObject
end get
end Property
end class
事实证明,这是更有效,因为对象被拒之门外的记忆,他们需要的,直到(Get方法被访问)。 它在限制的数据库访问和存储空间巨大收益提供了非常大的性能提升。
Answer 4:
你仍然需要担心,当你正在编写托管代码,除非你的应用程序是微不足道的记忆。 我会建议两件事情:第一, 阅读因为它会帮助你理解.NET的内存管理。 第二,学会使用像CLRProfiler(微软)的工具。 这可以给你是什么原因造成的内存泄漏的想法(例如,你可以看看你的大对象堆碎片)
Answer 5:
您是否使用非托管代码? 如果您不使用非托管代码,按照微软的说法,传统意义上的内存泄漏是不可能的。
应用程序使用的内存可能不但是释放出来,因此应用程序的内存分配可以在整个应用程序的生命成长。
从如何在Microsoft.com确定公共语言运行时内存泄漏
当您使用非托管的代码作为应用程序的一部分内存泄漏可能发生在.NET Framework应用程序。 此非托管的代码可以泄漏内存,和.net框架运行时无法处理这一问题。
此外,一个项目可能只出现有内存泄漏。 如果很多大型对象(如DataTable对象)声明,然后添加到集合(如数据集),可能会发生这种情况。 这些对象拥有的资源可能永远不会被释放,而剩下资源的延续,同时程序的整个运行。 这似乎是一个泄漏,但实际上它只是一个内存在程序被分配方式的症状。
对于处理这类问题,你可以实现IDisposable的 。 如果你想看到的一些策略来处理内存管理,我建议寻找IDisposable的,XNA,内存管理 ,游戏开发者需要有更多的可预测的垃圾收集等必须强制GC做它的事。
一个常见的错误是不能删除的事件处理程序订阅的对象。 事件处理程序订阅将防止对象被回收。 另外,看看在使用语句,它允许您创建一个资源的生命周期范围有限。
Answer 6:
此博客已使用的WinDbg和其他的工具来跟踪所有类型的内存泄漏一些非常精彩的演练。 优秀的阅读来发展你的技能。
Answer 7:
我刚在一个窗口服务中的内存泄漏,我固定的。
首先,我想MemProfiler 。 我发现它真的很难使用,而不是在所有用户友好。
然后,我用JustTrace这是更容易使用,为您提供有关不正确配置的对象更多的细节。
它让我真正轻松地解决内存泄漏。
Answer 8:
如果你正在观察的泄漏是由于失控的缓存实现,这是一种情况,你可能要考虑使用的WeakReference的。 这将有助于确保在必要时内存被释放。
但是,恕我直言,这将是更好地考虑定制的解决方案 - 只有你真的知道你需要多长时间才能保持周围的对象,所以设计合适的家政服务代码,您的具体情况,通常是最好的办法。
Answer 9:
大枪- Windows调试工具
这是一个工具的惊人的收藏。 您可以分析它托管和非托管堆,你可以脱机做到这一点。 这是用于调试的是保持回收由于内存过度使用我们的ASP.NET应用程序的一个非常方便的。 我只需要创造生活过程生产服务器上运行一个完全内存转储,所有的分析是在WinDbg中离线进行。 (原来一些开发商被过度使用内存中会话存储。)
“如果打破它......”博客在这方面还非常有用的文章。
Answer 10:
要记住的最好的事情是保持跟踪引用到你的对象。 这是很容易吊引用,你不关心了对象就结了。 如果您不打算再使用的东西,摆脱它。
习惯使用滑动过期缓存提供商,因此,如果事情没有在期望的时间窗口引用它取消引用和清理。 但是,如果它被访问了很多它会在内存中说。
Answer 11:
一个最好的工具是使用Windows调试工具 ,并考虑使用ADPlus的进程的内存转储,然后使用WinDbg和SOS插件来分析进程的内存,线程和调用堆栈。
您可以使用此方法用于识别服务器的问题太多,安装工具后,共享目录,然后使用(NET USE)从服务器连接到共享,要么采取崩溃或挂起的过程中转储。
然后分析离线。
Answer 12:
我修复管理的应用程序之一后,我有同样的事情,怎么样来验证我的应用程序不会有我的下一个变化之后相同的内存泄漏,所以我写的东西一样释放对象验证框架,请看看的NuGet包ObjectReleaseVerification 。 您可以在这里找到一个样本https://github.com/outcoldman/OutcoldSolutions-ObjectReleaseVerification-Sample ,以及有关该样本http://outcoldman.ru/en/blog/show/322
Answer 13:
Answer 14:
在Visual Studio 2015年考虑使用现成的内存使用诊断工具来收集和分析内存使用情况的数据。
该内存使用工具,您可以采取托管和本机内存堆的一个或多个快照,以帮助了解对象类型的内存使用情况的影响。
文章来源: What strategies and tools are useful for finding memory leaks in .NET?