"!heap -flt -s xxxx" windbg 命令中的不同列代表啥
Posted
技术标签:
【中文标题】"!heap -flt -s xxxx" windbg 命令中的不同列代表啥【英文标题】:What do the different columns in the "!heap -flt -s xxxx" windbg command represent"!heap -flt -s xxxx" windbg 命令中的不同列代表什么 【发布时间】:2011-10-04 23:16:59 【问题描述】:我一直在做一些关于高内存问题的工作,我一直在 windbg 中进行大量堆分析,我很好奇“!heap -flt -s xxxx”命令中不同列的真正含义.
我阅读了What do the 'size' numbers mean in the windbg !heap output?,并查看了我的“Windows Internals”一书,但我仍然有很多问题。所以列和我的问题如下。
**HEAP_ENTRY** - What does this pointer really point to? How is it different than UserPtr?
**Size** - What does this size mean? How is it different than UserSize?
**Prev** - This just appears to be the negative offset to get to the previous heap entry. Still not sure exactly how it's used.
**Flags** - Is there any documentation on these flags?
**UserPtr** - What is the user pointer? In all cases I've seen it's always 8 bytes higher than the HEAP_ENTRY, but I don't really know what it points to.
**UserSize** - This appears to be the size of the actual allocation.
**state** - This just tells you what state of this heap entry is (free, busy, etc....)
Example:
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
0015eeb0 0044 0000 [07] 0015eeb8 00204 - (busy)
【问题讨论】:
好问题.. 我也想知道同样的事情 【参考方案1】:通过查看 Debugging Tools for Windows 帮助文件中的 !heap 文档和 MSDN 上的堆文档以及来自 Advanced Windows Debugging 的出色 excerpt,以下是我能够汇总的内容:
HEAP_ENTRY:指向堆内入口的指针。如您所见,有一个 8 字节的标头,其中包含 HEAP_ENTRY 结构的数据。 HEAP_ENTRY 结构的大小是 8 个字节,它定义了“堆粒度”大小。这用于确定... SIZE:条目的粒度大小(即分配大小/8) FLAGS:这些在 winbase.h 中定义,并在 MSDN 链接中找到解释。 USERPTR:指向已分配(或已释放)对象的实际指针【讨论】:
【参考方案2】:嗯,HEAP_ENTRY 和 UserPtr 之间的主要区别在于,堆必须被索引、分配、填充元数据(如分配给用户的长度)......否则,你怎么能释放( p)没有提供分配多少字节的东西?两个大小字段相同:一是索引堆的结构有多大,一是可供用户使用的内存区域有多大。
反过来,FLAGS 基本上指定分配的内存块的哪些属性,如果它被提交或只是保留,并且,我猜,如果需要,内核使用它来重新排列或共享内存区域(但正如 nithins 指定的那样记录在 MSDN 中)。
PREV ptr 用于跟踪所有分配的区域,第一个指针存储在 PEB 结构中,因此用户空间和内核空间代码都知道分配的堆池。
【讨论】:
【参考方案3】:HEAP_ENTRY 堆将分配的块存储在连续的内存段中,每个分配的块以一个 8 字节的标头开头,后跟实际分配的数据。 HEAP_ENTRY 列是分配块头的开始地址。
尺寸 堆管理器以 8 个字节的倍数处理块。该列是分配的 8 字节块的数量。在您的示例中,0044 表示该块占用 0x220 字节 (0x44*8)。
上一个 乘以 8 得到前一个堆块的负偏移量(以字节为单位)。
标志 这是对以下信息进行编码的位掩码
0x01 - HEAP_ENTRY_BUSY
0x02 - HEAP_ENTRY_EXTRA_PRESENT
0x04 - HEAP_ENTRY_FILL_PATTERN
0x08 - HEAP_ENTRY_VIRTUAL_ALLOC
0x10 - HEAP_ENTRY_LAST_ENTRY
用户指针 这是 HeapAlloc(由 malloc/new 调用)函数返回给应用程序的指针。由于标头始终为 8 字节长,因此始终为 HEAP_ENTRY +8。
用户大小 这是通过 HeapAlloc 函数的大小。
状态 这是对 Flags 列的解码,告诉条目是否忙、已释放、其段的最后一个……
请注意,在 Windows 7/2008 R2 中,堆默认使用名为 LFH(低碎片堆)的前端,该前端使用默认堆管理器来分配块,在其中分派用户分配的数据。对于这些堆,UserPtr 和 UserSize 不会指向真实的用户数据。
!heap -s
的输出显示启用了 LFH 的堆。
【讨论】:
你碰巧知道如何在 LFH 堆中获取真正的 userptr(这就是最初引发这个问题的原因)? !heap -p 了解 LFH,但选择较少。您可以使用 !heap -p -a 从地址获取真正的 userptr。 !heap -p -all 将列出所有堆的所有用户块。如果您在文件中重定向输出,则可以使用 grep 查找所需用户大小的块。 线程已经很老了,但请注意,对于 x64,用户 ptr 位置是 HEAP_ENTRY +16,因为来自 ntdll.dll 的sizeof(_HEAP_ENTRY)
返回 0x10 / 16 字节。此外,较新版本的 WinDBG 似乎正确地将 UserPtr 映射到数据,尽管我还不知道他们在旧版本中如何或为什么不这样做以上是关于"!heap -flt -s xxxx" windbg 命令中的不同列代表啥的主要内容,如果未能解决你的问题,请参考以下文章
Webpack打包报"JavaScript heap out of memory"错误
Webpack打包报"JavaScript heap out of memory"错误
2Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
eclipse里报:An internal error occurred during: "Building workspace". Java heap space(内存溢出)(示