【问题标题】:Can reserved memory cause an Out Of memory exception保留内存是否会导致内存不足异常
【发布时间】:2014-06-07 08:25:49
【问题描述】:

我们有一个 32 位 Windows 服务会泄漏内存 - 引发 OutOfMemory 异常。它是在 windows server 2003 上运行的 .net 4.0 可执行文件。在使用 WinDbg 调试故障转储文件时,我看到大部分内存实际上是保留的,没有提交。

从 WinDbg 屏幕截图中可以看出,有 2.5 Gb 的未分类内存使用量,其中大部分 2.1 Gb 实际上是保留内存 (MEM_RESERVE)。我有调试粉碎转储的经验,但这种情况对我来说是新事物。 MEM_COMMIT 退出 OK - 564.270 Mb,托管堆大小约为 82 Mb

我还检查了本机堆,看看是否有大块数据保留,但在那里也找不到任何可疑的东西

所以我的问题是 - MEM_RESERVED 是否可能导致 OOM 异常?如果是这样,我该如何调试它,看看为什么/有多少内存被保留?您还会在哪里寻找可能存在的问题?

如果需要任何其他信息,请询问,我会更新我的帖子。

【问题讨论】:

    标签: .net memory memory-management out-of-memory windbg


    【解决方案1】:

    是的,保留内存可以触发OutOfMemoryException。尝试分配几个非常大的字节数组。在您写入数组的内容之前,不会提交这些内存。但是,只需分配这些数组,您就可以轻松触发 OOM。

    我不知道实现细节,但由于如果 VirtualAlloc 不能满足保留请求,它将失败,我假设 CLR 将其转换为异常。我看不出它如何将失败的预留请求变成有用的东西,所以例外是一个明智的选择。

    【讨论】:

    • 感谢回复,你知道我怎么能看到WinDbg中保留了这么大的内存吗?
    • 假设内存被托管对象使用,您可以使用!dumpheap!do 检查这些内存。但是,鉴于!eeheap 的输出显示托管堆很小,我假设其他东西保留了此内存。
    • 你能指定还有什么可以保留内存吗?我很困惑,因为我希望“某物”要么在托管堆上,要么在本机堆上的一些本机资源上——它们都没有指向任何可疑的东西。还有什么可以保留内存?我很乐意立即检查。
    • 我的意思是“本地”。正如我所说,如果保留内存支持托管对象,您将能够在托管堆上找到这些对象。由于这似乎不是本机库或运行时本身的候选者,但我不能肯定地说。您可以通过查看!eeheap 的输出来获取有关 CLR 分配的更多信息。
    【解决方案2】:

    OutOfMemoryException 如果系统无法为您的应用程序分配更多虚拟内存,则会发生。保留内存是虚拟内存,因此会受到该限制。

    您可以最轻松地在 C++ 中尝试:

    while(::VirtualAlloc(NULL, 65536, MEM_RESERVE, PAGE_READWRITE) != NULL );
    std::cout << "All memory reserved. Now check with tools." << std::endl;
    

    如果 VirtualAlloc() 返回 NULL,它不能分配更多的内存。在 WinDbg 中会显示

    MEM_RESERVE   32307  7f6f2000 (1.991 Gb)  99.59%   99.56%
    

    但是,VirtualAlloc() 不会在堆上分配内存,所以!heap 在这种情况下没有用,只显示默认进程堆:

    0:000> !heap
    Index   Address  Name      Debugging options enabled
      1:   00440000 
    

    反之亦然:堆管理器使用 VirtualAlloc() 来获取内存。另请注意,.NET 也不使用堆管理器。它还使用 VirtualAlloc() 直接分配内存,然后自行管理。因此,因为您可以在 !heap 的输出中看到它,所以这不是 .NET 问题,而是本机内存问题。

    在我的幼稚理解中,gflags 设置 Enable heap tagging by DLL 应该有助于确定堆分配的来源。然而,我期望命令!heap -t 会简单地显示分配内存的DLL 的名称并没有实现。

    【讨论】:

    • 感谢您的意见。我试过 !heap -t 命令,但它没有提供任何有用的东西。我正在尝试挖掘本机内存,看看我能在那里找到什么。非常欢迎任何其他检查其他内容的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-15
    • 2011-05-26
    • 2013-06-22
    • 2013-12-09
    • 1970-01-01
    • 2011-09-02
    • 2011-04-10
    相关资源
    最近更新 更多