6

故事:

我们在 .NET 2.0 应用程序中面临非托管内存泄漏。启动后的进程消耗大约 150MB(其中大部分是 .NET 托管、对象状态等)。运行大约 12 小时后,进程消耗了 800MB,接下来的 12 小时后,进程有大约 1.8GB 的​​ RAM。我刚刚尝试了 JetBrains .NET Memory Profiler、ANTS、.NET Memory Profiler(以及市场上可能有的 2 个下一个 mem 配置文件),这些都没有帮助我,因为我后来检测到我们的进程在未管理的非托管区域中消耗了那么多内存。为了检测到这一点,我使用了带计数器的 Perf 监视器:私有字节(进程)和所有堆中的#字节(.NET CLR 内存),其中私有字节消耗进程分配的所有内存的大约 90%。这就是我切换到非托管调试的原因。

DebugDiag:所以我在进程上运行 debugdiag 并获得完整转储,这是它的快照:

  • mscorwks.dll(一个已知的 Windows 内存管理器)负责 781,73 MB 的未完成分配。这些分配似乎源自以下模块和功能:

  • ntdll.dll(一个已知的 Windows 内存管理器)负责 98,24 MB 的未完成分配。这些分配似乎源自以下模块和功能:

按分配计数排名前 4 位的函数

  • mscorwks!EEHeapAlloc+15b -- 80 957 个分配
  • mscorwks!CLRMapViewOfFileEx+4a -- 4 171 个分配

按分配大小排列的前 4 个函数

  • mscorwks!EEVirtualAlloc+15b -- 117,50 MB
  • mscorwks!EEHeapAlloc+15b -- 15,03 MB

发现有趣的日志:

功能详情

Function mscorwks!EEVirtualAlloc+15b

  • 分配类型 虚拟内存分配
  • 分配计数 1471 个分配
  • 分配大小 117,50 MB
  • 泄漏概率 73%

Function mscorwks!EEHeapAlloc+15b

  • 分配类型 堆分配
  • 分配计数 80957 个分配
  • 分配大小 15,03 MB
  • 泄漏概率 72%

Function mscorwks!CExecutionEngine::CheckThreadState+fe

  • 分配类型 堆分配
  • 堆句柄 0x00000000`00000000
  • 分配计数 2 个分配
  • 分配大小 304 字节
  • 泄漏概率 98%

Function mscorwks!CLRMapViewOfFileEx+4a

  • 分配类型 虚拟内存分配
  • 分配计数 4171 个分配
  • 分配大小 0 字节
  • 泄漏概率 73%

我希望有人把我推向正确的方向我怎么能从这个转储中找到内存泄漏?我能够将转储加载到 windbg 并运行标准的 windbg 命令集,但我不知道哪个是能够隔离泄漏的正确命令。

如果有人想提供帮助,我可以提供完整的转储。

4

3 回答 3

3

查看转储文件,它似乎确实是一个托管泄漏,只是不在托管堆上。转储显示托管堆非常小,但加载器堆为 1 GB。该流程有超过 35000 个动态程序集。我查看了其中一些,它们似乎是序列化(XML 和二进制)。看看这篇博文。它描述了一个类似的问题。

于 2012-10-05T16:56:25.240 回答
1

我最喜欢的调试 .NET 和 Silverlight 内存泄漏的方法是使用 SOS 扩展。请参阅此处进行快速演练:http: //blogs.msdn.com/b/ricom/archive/2004/12/10/279612.aspx

我一般做的是:

  1. !DumpHeap -stat 获取内存中存在哪些对象的列表;这通常会表明问题的根源(例如,如果我看到一百万只应该使用一次并丢弃的小物体)。
  2. 一旦我知道是什么类型的对象导致它,我使用!DumpHeap 转储这些对象的列表并随机获取其中一些对象的根(!GCRoot)。这通常表明哪个对象意外地持有对泄漏对象的引用。

这假设您正在处理托管内存泄漏(引用被保存在您不期望的地方)。如果您正在处理非托管内存泄漏,这将无济于事,但除非您的应用程序执行大量手动非托管内存管理(例如 P/Invoke 的对象编组),否则这种情况不太可能发生。

于 2012-10-04T12:11:29.290 回答
0

使用弱引用可能会减少内存使用http://en.wikipedia.org/wiki/Weak_reference .. 这很一般,但是一旦它为我节省了几乎几 GB 秒

于 2012-10-04T12:00:18.670 回答