.net - .net 应用程序中的内存泄漏 + 奇怪的 GC 行为

标签 .net memory-leaks debugdiag performance-monitor

我不太确定该去哪里寻求帮助,所以我想我应该尝试 stackoverflow,因为它通常可以回答我所有与编程相关的大约 90% 的问题。

简而言之,我有一个正在泄漏内存的开源 .NET 应用程序。从某种意义上说,这可能不是真正的内存泄漏,当应用程序关闭时,我怀疑内存被回收,但在它运行时,它不断分配更多内存而不释放它。最终,抛出System.OutOfMemoryException

为了调试该问题,我按照this article中推荐的步骤进行操作。 ,并生成了下图,其中红色是 .NET/CLR 内存“所有堆中的#Bytes”,绿色是 Windows 性能监视器工具的进程“私有(private)字节”(请注意,绿线已统一按比例缩小以显示更接近红线,因为只有线条的形状对我来说很重要):Performance Monitor Output .

我将该图像作为托管内存泄漏的证据,并随后使用 Windows 的调试诊断工具来尝试找到泄漏源(如文章中所述)。然而我从调试诊断工具返回的报告非常奇特。

基本上,我尝试在应用程序运行时每 5 秒收集一次“完整 UserDump”,但都因垃圾收集器始终处于垃圾收集器中间而受阻。当时的垃圾收集周期,导致调试诊断工具输出错误,并阻止其收集任何有用的 .NET 内存相关信息。

现在我陷入困境,我知道我有托管内存泄漏,但我不知道如何缩小它的范围。我还对垃圾收集器如何始终处于收集周期的中间感到困惑,这让我想知道垃圾收集线程是否以某种方式被阻塞,从而阻止它释放内存和/或退出垃圾收集周期。

性能监视器图的某些部分中分配的 .NET 内存略有下降,因此垃圾收集器不会永远卡住,但大多数时间肯定是这样,否则调试诊断应该已被卡住能够执行 UserDump。

几个问题:

  1. .NET 应用程序中的垃圾收集器在尝试释放一些内存(可能来自某些编码不良的析构函数/终结器或其他内容)时是否可能会卡住?

  2. 我可以使用什么策略来继续缩小问题根源的范围?

最佳答案

如果您提供.NET Framework 版本、操作系统版本、进程位数以及计算机上的处理器数量,将会有所帮助。如果您很快就会遇到内存不足异常,这会让我认为您正在运行 32 位进程,但如果您能确认,仍然会有所帮助。

首先,您应该通过查找进程的 %Time in GC 内存计数器来检查 GC 是否确实是问题的原因。您可以在 .NET CLR 内存对象下的 PERFMON 中监视这一点。如果此计数器 > 30%,则肯定存在 GC 问题。您粘贴的 PNG 并没有告诉我每秒分配了多少内存,因此如果内存很高,那么 GC 就会启动更多内存。

需要注意的是,使用最新的调试诊断工具来分析转储并查看是否看到不同的内容。 DebugDiag 1.2 中存在一个问题,可能会导致错误地报告“垃圾收集中间”消息,因此您需要确保 GC 在转储时是否确实在运行。您可以从 http://www.microsoft.com/en-us/download/details.aspx?id=40336 下载最新版本并使用该工具分析相同的转储文件,看看是否报告了不同的内容。另外,在报告中搜索 GarbageCollectionGeneration 字符串,该字符串将显示负责调用 GC 的线程。查看该线程的堆栈,您也许能够识别该线程正在执行的操作最终调用了 GC。这可能有帮助,也可能没有帮助。

回答您的其他问题:-

1) 如果任何线程禁用了 PRE-EMPTIVE GC,GC 可能会卡住。您可以阅读文章 http://blogs.msdn.com/b/tess/archive/2008/02/11/hang-caused-by-gc-xml-deadlock.aspx 详细了解 PRE-EMPTIVE GC 以及如何找出禁用了 pre-emptive GC 的线程。

2) 我会在 WinDBG 中打开转储,并按照上面博客中提到的方法查看是否到达某个地方。如果框架是 .net Framework 4.0 或更高版本,您还可以使用 PERFVIEW 工具来收集跟踪,这可以提供有关 GC 发生原因的良好信息。查看 PERFVIEW 的视频来解决 http://channel9.msdn.com/Series/PerfView-Tutorial/PerfView-Tutorial-9-NET-Memory-Investigation-Basics-of-GC-Heap-Snapshots 处的 GC 问题

此外,如果此 EXE 正在进行一些后台处理,您可能需要启用 GC 的服务器模式,看看是否有帮助。请阅读文章 http://blogs.msdn.com/b/clyon/archive/2004/09/08/226981.aspx 了解更多信息。

希望这有帮助!!!

关于.net - .net 应用程序中的内存泄漏 + 奇怪的 GC 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16451982/

相关文章:

c# - System.Web.Http Server 是否对 ASP.Net Web API 单元测试表现良好?

.net - 有没有办法免费试用 Windows Azure?

c# - 如何加载ascx文件中的资源 key ?

c++ - 删除所有动态内存后出现 valgrind 泄漏错误

asp.net - 如何在应用程序池回收后获取特定异常的内存转储

c# - 为什么 object.ToString() 没有反函数?

Haskell:如何摆脱内存泄漏

c++ - 如何自己管理内存? memory_manager.exe : 0xC0000005: Access violation reading location 0x00000004 中 0x00423e3b 处未处理的异常

azure - 是否可以从 Azure Web 角色实例下载转储文件

.Net Core DebugDiag 等价物