【问题标题】:How to locate unmanaged memory leak in c#如何在 C# 中定位非托管内存泄漏
【发布时间】:2021-03-17 11:30:14
【问题描述】:

我对我们的应用程序中的内存泄漏感到困惑。它只发生在客户的机器上,或者至少在我的机器上重现它的测试失败了。幸运的是,如果发生未处理的异常,我们的应用程序会将一些数据收集到日志文件中,如果它是 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 听起来并不多。

此时我不知道如何继续 我如何找到这么多丢失的内存? 我如何知道它是否是第三方程序集以及哪一个?

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

【问题讨论】:

  • 您最好通过support.microsoft.com 打开支持案例以获得帮助。转储分析并非易事。
  • 感谢李的提示。我担心如果我不能很快到达任何地方,我可能不得不这样做,但我认为我更进一步。我得到了一个新的 MemoryDump,它启用了更多选项。我不能通过 !address -summary 命令看到确实 1,236GB 被 占用。如果我理解这一点,这意味着它是非托管内存(可能是图像?)并且可能由第三方 dll 加载。任何提示如何找出这种未知的记忆东西是什么类型?
  • !heap -s 没有显示任何丢失的 1,2 GB。这一切都归结为托管堆的大小。没有列出任何虚拟块。
  • 找到另一个线索:命令 !GCHandleLeaks 列出了 2288 个条目。这看起来不正常。这个输出到底想告诉我什么?我在任何地方都找不到有关此命令的太多文档
  • <unknown> 也可以是 .NET 内存。您必须通过其他方式排除这种情况(例如!eeheap -gc,就像您所做的那样)。见stackoverflow.com/a/39428167/480982

标签: c# memory out-of-memory windbg unmanaged-memory


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2012-01-30
    • 1970-01-01
    • 2020-07-11
    • 2016-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    • 1970-01-01
    相关资源
    最近更新 更多