【问题标题】:windbg diagnosing leaks in 64-bit dumps - !heap not showing memory growthwindbg 诊断 64 位转储中的泄漏 - !堆未显示内存增长
【发布时间】:2018-11-05 15:51:29
【问题描述】:

我正在尝试调试 64 位 C++ 本机应用程序中的内存泄漏。该应用程序每秒泄漏 1300 个字节 7-10 次 - 通过普通的 malloc()。

如果我使用 WinDBG 附加到进程并每隔 60 秒进入它,!heap 不会显示分配的内存有任何增加。

我确实在进程上启用了用户模式堆栈跟踪数据库:

gflags /i <process>.exe +ust

在 WinDBG 中(成功加载所有符号),我正在使用:

!heap -stat -h

但是,即使我可以看到任务管理器中的 Private Bytes 增加和 PerfMon 跟踪,当我闯入时,命令的输出也不会改变。

我知道,当分配较小时,它们转到 HeapAlloc(),当它们较大时,它们转到 VirtualAlloc。 !heap 对 HeapAlloc 不起作用吗?

post 似乎暗示使用 DebugDiag 可能会起作用,但它仍然归结为使用 WinDBG 命令来处理转储。试过没用。

这个post 还说 !heap 命令对于 64 位应用程序已损坏。会这样吗?

是否有用于诊断 64 位应用程序泄漏的替代程序?

【问题讨论】:

  • 使用 WinDBG 时不涉及转储。我直接附加到这个过程。无论如何,UMDH 也没有显示任何泄漏。
  • 您最好通过support.microsoft.com 打开支持案例以获取帮助。在 SO 上讨论此类内容过于广泛,因为没有人可以复制您所拥有的。
  • 你有minimal reproducible example吗?您的第一段听起来可以用 20 行代码来实现。你能给我们一些我们可以尝试的东西吗?可以分享app或dmp文件吗?
  • 这是 450 万行代码。我会看看我是否可以创建一个可管理的示例。

标签: windbg


【解决方案1】:

!heap 没有显示分配的内存有任何增加。

这可能取决于您正在查看的列以及堆管理器之前分配了多少内存。

例如您的应用程序可能有 100 MB 的堆,其中只有一些 64kB 的块从“保留”列移动到“已提交”列。如果内存从一开始就被提交,那么使用普通的!heap 命令将根本看不到任何内容。

我确实在进程上启用了用户模式堆栈跟踪数据库

这将帮助您获得分配堆栈跟踪,但一般不会影响泄漏。

我知道,当分配较小时,它们会转到 HeapAlloc(),当它们较大时,它们会转到 VirtualAlloc。

是的,for allocations > 512k

!heap 对 HeapAlloc 不起作用吗?

应该的。而且由于 C++ malloc()new 都使用 Windows 堆管理器,它们迟早会产生 HeapAlloc()

以下代码

#include <iostream>
#include <chrono>
#include <thread>

int main()
{
    // https://stackoverflow.com/questions/53157722/windbg-diagnosing-leaks-in-64-bit-dumps-heap-not-showing-memory-growth
    //
    // I am trying to debug a memory leak in a 64-bit C++ native application.
    // The app leaks 1300 bytes 7-10 times a second - via plain malloc().

    for(int seconds=0; seconds < 60; seconds++)
    {
        for (int leakspersecond=0; leakspersecond<8;leakspersecond++)
        {
            if (malloc(1300)==nullptr)
            {
                std::cout << "Out of memory. That was unexpected in this simple demo." << std::endl;
            }
            std::this_thread::sleep_for(std::chrono::milliseconds(125));
        }
    }
}

编译为 64 位发布版本并在 WinDbg 10.0.15063.400 x64 显示中运行

0:001> !heap -stat -h

Allocations statistics for
 heap @ 00000000000d0000
group-by: TOTSIZE max-display: 20
    size     #blocks     total     ( %) (percent of total busy bytes)
    514 1a - 8408  (32.24)
    521 c - 3d8c  (15.03)
[...]

以后

0:001> !heap -stat -h

Allocations statistics for
 heap @ 00000000000d0000
group-by: TOTSIZE max-display: 20
    size     #blocks     total     ( %) (percent of total busy bytes)
    514 30 - f3c0  (41.83)
    521 18 - 7b18  (21.12)

即使没有设置+ust

这是 450 万行代码。

那么你怎么知道它通过普通的 malloc() 泄漏了 1300 个字节?

【讨论】:

  • 预计这不是一个完整的答案。评论太多了。一旦 OP 提供 MCVE 或类似内容,我将删除答案。
  • 我们知道快速增长的私有字节存在泄漏。代码审查发现了一个明显的指针重新分配,该指针重新分配了孤立的内存。作为我们解决缺陷的一部分,我必须将泄漏显示为测试用例的一部分(然后是解决方案,这证明它已修复。)我希望使用 WinDGB 记录泄漏,而不仅仅是 PerfMon。这就是开始的地方。
  • @cardinalPilot:好的,当你编译和调试我的代码时会发生什么?
  • 叹息。您的代码按预期工作。当我从我们的代码库中取出有问题的代码并对其进行测试时,它也有效。我想知道它是否与 DLL 中的 malloc 有关。无论如何,问题似乎只在于它是更大代码库的一部分。
猜你喜欢
  • 2021-11-06
  • 2018-10-24
  • 2012-10-09
  • 2012-03-19
  • 2015-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多