如何在c#中定位非托管内存泄漏

问题描述

我对我们的应用程序中的内存泄漏感到有些困惑。它只发生在客户的机器上,或者至少在我的机器上重现它的测试失败了。幸运的是,我们的应用程序在发生未处理的异常时将一些数据收集到日志文件中,如果是 OOM,则写入转储文件。它是一个 32 位 C# WinForms 程序。

到目前为止我能发现什么:

  1. 进程在崩溃前运行了大约三个小时

  2. 在崩溃时收集了以下值:

currentProcess.WorkingSet64 = 1,8 GB currentProcess.VirtualMemorySize64 = 2.0 GB currentProcess.PrivateMemorySize64 = 680 MB

这是第一个让我认为它不受管理的点。为什么 WorkingSet 比 PrivateMemory 高这么多?我猜可能是第三方 dll?

为了进一步分析,我将内存转储加载到 WinDbg

  1. SOS 命令 !analyzeoom 告诉我:由于 GC 堆上的分配,没有托管 OOM。为了验证我查看了 !eeheap,它告诉我 GC 堆的总大小为 217 MB,而 Loader 堆的总大小为 38 MB

  2. 现在我想看看所有的堆。但是使用 !heap -s 显示 Commited Bytes 170 MB 的组合值

  3. !dumpheap -stat 再次显示最大的消费者大约是 10-25 MB。还有大约 4000 个免费对象,共 38 MB。

最后一个值让我觉得可能OOM是碎片造成的。但是 38 MB 听起来并不多。

此时我不知道如何继续 如何找到大量丢失的内存? 我如何确定它是第三方程序集还是哪个程序集?

遗憾的是,我无法共享内存转储,因为它包含敏感的客户数据。但我很感激任何建议/提示

解决方法

这是一个带有错误配置的 ImageCache 选项的 PDF 查看器组件。 谢谢大家的帮助