【发布时间】:2021-03-17 11:30:14
【问题描述】:
我对我们的应用程序中的内存泄漏感到困惑。它只发生在客户的机器上,或者至少在我的机器上重现它的测试失败了。幸运的是,如果发生未处理的异常,我们的应用程序会将一些数据收集到日志文件中,如果它是 OOM,则写入转储文件。它是一个 32 位 C# WinForms 程序。
到目前为止我能找到什么:
-
进程在崩溃之前运行了大约三个小时
-
在崩溃时收集了以下值:
currentProcess.WorkingSet64 = 1,8 GB currentProcess.VirtualMemorySize64 = 2.0 GB currentProcess.PrivateMemorySize64 = 680 MB
这是让我认为它不受管理的第一点。为什么 WorkingSet 比 PrivateMemory 高这么多?我猜可能是第三方 dll?
为了进一步分析,我将内存转储加载到 WinDbg 中
-
SOS 命令 !analyzeoom 告诉我:由于 GC 堆上的分配,没有托管 OOM。为了验证,我查看了 !eeheap,它告诉我 GC 堆的总大小为 217 MB,Loader 堆的总大小为 38 MB
-
现在我想看看所有的堆。但是使用 !heap -s 显示 Commited Bytes 170 MB 的组合值
-
!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