gpt4 book ai didi

heap-memory - !heap -stat -h 不显示分配

转载 作者:行者123 更新时间:2023-12-01 02:04:23 30 4
gpt4 key购买 nike

我试图确定为什么我的应用程序消耗 4GB 的私有(private)字节。所以我做了一个完整的内存转储,将它加载到windbg中。但是使用 !heap -stat -h 进行分析产生不加起来的奇怪结果:

0:000> !heap -s
(...)
Heap Flags Reserv Commit Virt Free List UCR Virt Lock Fast
(k) (k) (k) (k) length blocks cont. heap
-------------------------------------------------------------------------------------
000002d0a0000000 00000002 2800804 2780508 2800700 2984 1980 177 0 6 LFH
000002d09fe10000 00008000 64 4 64 2 1 1 0 0
000002d09ff70000 00001002 1342924 1334876 1342820 13042 3342 87 0 0 LFH

好的,我有一个 2.8GB 堆和一个 1.34GB 堆。让我们看一下第一个的分配:
0:000> !heap -stat -h 000002d0a0000000 
heap @ 000002d0a0000000
group-by: TOTSIZE max-display: 20
size #blocks total ( %) (percent of total busy bytes)
651 291 - 1035e1 (16.00)
79c 1df - e3ce4 (14.06)
28 156d - 35908 (3.31)
(...)

IIUC,第一行表示 block 大小 0x651(=1617 字节), block 数 0x291(=657),总字节数为 0x103531(=1062369 字节 =~1MB),占总繁忙字节的 16%。但是查看摘要,应该有 ~2.8GB 的​​繁忙字节!

另一个差距:
0:000> !heap -stat -h 000002d0a0000000 -grp A
heap @ 000002d0a0000000
group-by: ALLOCATIONSIZE max-display: 20
size #blocks total ( %) (percent of total busy bytes)
a160 1 - a160 (0.62)
7e50 2 - fca0 (0.97)

0:000> !heap -h 000002d0a0000000
(...)
(509 lines that note allocations with size 7e50, like this one:)
000002d0a3f48000: 11560 . 07e60 [101] - busy (7e50)

编辑:许多行还说 Internal最后, appears to mean HEAP_ENTRY_VIRTUAL_ALLOC - 但是有 (7e50) 的 509 行不。

我的问题:我怎样才能得到 !heap -stat -h显示所有分配,因此它们加起来为 !heap -s 的输出?

最佳答案

目前我只能解释繁忙百分比,但这可能已经有所帮助。它的值(value)有点误导。

虚拟内存是取自 VirtualAlloc() 的内存. C++ 堆管理器使用该基 native 制从操作系统获取内存。该虚拟内存可以提交(准备使用)或保留(可以稍后提交)。 !heap -s 的输出告诉您关于该虚拟内存的堆的状态。

因此,我们同意 C++ 堆管理器可以使用的任何内存都是已提交内存。这个粗粒度的虚拟内存被 C++ 堆管理器分割成更细的 block 。堆管理器可以分配这些较小的 block 并释放它们,这取决于 malloc() 的需要。/free()new/delete操作。

当 block 空闲时,它们不再忙。同时,C++ 堆管理器可能决定不将空闲 block 还给操作系统,因为

  • 它不能,因为 64k 虚拟内存的其他部分仍在使用中
  • 或者它不想(我们无法确切知道的内部原因,例如性能原因)

  • 由于空闲部分不算繁忙,因此与虚拟内存相比,繁忙百分比似乎太高了。

    映射到您的情况,这意味着:
  • 您有 2.8 GB 的虚拟内存
  • 在堆中 000002d0a0000000 ,您有 ~1 MB/16% = 6.25 MB 的内存在使用中,其余的可能在空闲堆 block 中(可能不是)

  • 以下示例基于此 C++ 代码:
    #include "stdafx.h"
    #include <iostream>
    #include <Windows.h>
    #include <string>
    #include <iomanip>

    int main()
    {
    HANDLE hHeap = HeapCreate(0, 0x1000000, 0x10000000); // no options, initial 16M, max 256M
    HeapAlloc(hHeap, HEAP_GENERATE_EXCEPTIONS, 511000); // max. allocation size for non-growing heap
    std::cout << "Debug now, handle is 0x" << std::hex << std::setfill('0') << std::setw(sizeof(HANDLE)) << hHeap << std::endl;
    std::string dummy;
    std::getline(std::cin, dummy);
    return 0;
    }

    唯一的 511kB block 将被报告为 100%,尽管它只是 16 MB 的 ~1/32:
    0:001> !heap -stat -h 009c0000
    heap @ 009c0000
    group-by: TOTSIZE max-display: 20
    size #blocks total ( %) (percent of total busy bytes)
    7cc18 1 - 7cc18 (100.00)

    要查看免费部分,请使用 !heap -h <heap> -f :
    0:001> !heap -h 0x01430000 -f
    Index Address Name Debugging options enabled
    3: 01430000
    Segment at 01430000 to 11430000 (01000000 bytes committed)
    Flags: 00001000
    ForceFlags: 00000000
    Granularity: 8 bytes
    Segment Reserve: 00100000
    Segment Commit: 00002000
    DeCommit Block Thres: 00000200
    DeCommit Total Thres: 00002000
    Total Free Size: 001f05c7
    Max. Allocation Size: 7ffdefff
    Lock Variable at: 01430138
    Next TagIndex: 0000
    Maximum TagIndex: 0000
    Tag Entries: 00000000
    PsuedoTag Entries: 00000000
    Virtual Alloc List: 014300a0
    Uncommitted ranges: 01430090
    FreeList[ 00 ] at 014300c4: 01430590 . 0240e1b0
    0240e1a8: 7cc20 . 21e38 [100] - free <-- no. 1
    02312588: 7f000 . 7f000 [100] - free <-- no. 2
    [...]
    01430588: 00588 . 7f000 [100] - free <-- no. 32

    Heap entries for Segment00 in Heap 01430000
    address: psize . size flags state (requested size)
    01430000: 00000 . 00588 [101] - busy (587)
    01430588: 00588 . 7f000 [100]
    [...]
    02312588: 7f000 . 7f000 [100]
    02391588: 7f000 . 7cc20 [101] - busy (7cc18)
    0240e1a8: 7cc20 . 21e38 [100]
    0242ffe0: 21e38 . 00020 [111] - busy (1d)
    02430000: 0f000000 - uncommitted bytes.
    0:001> ? 7cc18
    Evaluate expression: 511000 = 0007cc18

    在这里,我们看到我有一个 256 MB 的堆(240 MB 未提交,0x0f000000 + 16 MB 已提交,0x01000000)。总结 FreeList 中的项目,我得到
    0:001> ? 0n31 * 7f000 + 21e38 
    Evaluate expression: 16264760 = 00f82e38

    所以几乎所有的东西(~16 MB)都被 C++ 堆管理器认为是空闲的而不是忙碌的。 !heap -s 报告了 16 MB 这样的内存在 WinDbg 6.2.9200 中以这种方式:
    0:001> !heap -s
    LFH Key : 0x23e41d0e
    Termination on corruption : ENABLED
    Heap Flags Reserv Commit Virt Free List UCR Virt Lock Fast
    (k) (k) (k) (k) length blocks cont. heap
    -----------------------------------------------------------------------------
    004d0000 00000002 1024 212 1024 6 5 1 0 0 LFH
    00750000 00001002 64 20 64 9 2 1 0 0
    01430000 00001000 262144 16384 262144 15883 32 1 0 0
    External fragmentation 96 % (32 free blocks)
    -----------------------------------------------------------------------------

    恕我直言,有一个关于保留和提交内存的错误:它应该是 262144k 虚拟 - 16384 提交 = 245760k 保留。

    请注意列表长度如何与之前报告的空闲 block 数相匹配。

    以上仅解释了繁忙百分比。剩下的问题是:您的案例中报告的可用内存与这种情况不匹配。

    通常我会说剩余内存在虚拟 block 中,即大于 512 kB(32 位)或 1 MB(64 位)的内存块,如 MSDN 中所述对于可增长的堆。但这里不是这样。

    没有关于虚拟 block 的输出,并且虚拟 block 的数量报告为0。

    生成虚拟 block 的程序将是
    #include "stdafx.h"
    #include <iostream>
    #include <Windows.h>
    #include <string>
    #include <iomanip>

    int main()
    {
    HANDLE hHeap = HeapCreate(0, 0x1000000, 0); // no options, initial 16M, growable
    HeapAlloc(hHeap, HEAP_GENERATE_EXCEPTIONS, 20*1024*1024); // 20 MB, force growing
    std::cout << "Debug now, handle is 0x" << std::hex << std::setfill('0') << std::setw(sizeof(HANDLE)) << hHeap << std::endl;
    std::string dummy;
    std::getline(std::cin, dummy);
    return 0;
    }

    !heap命令会提到虚拟 block :
    0:001> !heap -s
    LFH Key : 0x7140028b
    Termination on corruption : ENABLED
    Heap Flags Reserv Commit Virt Free List UCR Virt Lock Fast
    (k) (k) (k) (k) length blocks cont. heap
    -----------------------------------------------------------------------------
    006d0000 00000002 1024 212 1024 6 5 1 0 0 LFH
    001d0000 00001002 64 20 64 9 2 1 0 0
    Virtual block: 01810000 - 01810000 (size 00000000)
    00810000 00001002 16384 16384 16384 16382 33 1 1 0
    External fragmentation 99 % (33 free blocks)
    -----------------------------------------------------------------------------

    但是,在您的情况下,虚拟 block 的值是 0。也许这在您的 WinDbg 版本中报告为“内部”。如果您尚未升级,请尝试 6.2.9200 版本以获得与我相同的输出。

    关于heap-memory - !heap -stat -h 不显示分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33738306/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com