2011-07-14 127 views
15

我在高内存问题上做了一些工作,并且我一直在windbg中进行大量堆分析,而且我很好奇在“!heap -flt -s xxxx”命令中不同的列是什么意思。“!堆-flt -s xxxx”windbg命令中的不同列表示

我看了What do the 'size' numbers mean in the windbg !heap output?,我看了一下我的“Windows内部”书,但我仍然有一堆问题。所以列和我的问题在下面。 !

**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) 
+0

很好的问题..我想知道同样的事情 – pepsi

回答

18

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 

UserPtr 这是指针返回到由HeapAlloc应用功能(通过的malloc /新callbed)的位掩码。由于标题总是8个字节长,所以总是HEAP_ENTRY +8。

UserSize 这是传递HeapAlloc函数的大小。

状态 这是标志列的解码,告诉条目是否繁忙,释放,最后其细分市场中,...

要知道,在Windows 7/2008 R2,堆在默认情况下使用名为LFH(低碎片堆)的前端,它使用默认堆管理器来分配调度用户分配数据的块。对于这些堆,UserPtr和UserSize不会指向真实的用户数据。 !heap -s的输出显示哪些堆启用了LFH。

+1

你碰巧知道如何获得LFH堆中真正的userptr(这是什么原本是在推动这个问题)? – Zipper

+0

!堆-p知道LFH但有更少的选择。你可以用!heap -p -a

从地址获得真正的userptr。 !heap -p -all将列出所有堆的所有用户块。如果你将输出重定向到一个文件中,那么你可能会想要用户大小的块。 – plodoc

3

通过观察在调试工具的Windows帮助文件和MSDN堆文档,并从Advanced Windows Debugging很大excerpt堆文档,这里就是我已经能够放在一起:

  • HEAP_ENTRY:指向堆内的条目的指针。如您所见,有一个8字节的头部,其中包含HEAP_ENTRY结构的数据。 HEAP_ENTRY结构的大小是8个字节,它定义了“堆粒度”大小。这是用于确定...
  • SIZE:在粒度方面的条目的大小(即,分配大小/ 8)
  • FLAGS:这些在WINBASE.H定义与发现的解释在MSDN链接。
  • USERPTR:实际指针到所分配的(或释放)对象
0

那么,HEAP_ENTRY和UserPtr之间的主要差别是由于以下事实:堆已被编入索引,分配,填充有元数据(比如分配给用户的长度)......否则,你如何释放(p)某些内容而不提供分配的字节数?与两个大小字段相同的东西:一件事是堆索引的结构有多大,一件事是用户可以使用的内存区域有多大。

反过来,FLAGS基本上指定了分配的内存块的哪些属性(如果它已提交或只保留),以及我猜,如果需要,内核将使用它重新排列或共享内存区域(但是作为nithins指定他们在MSDN中记录)。

PREV ptr用于跟踪所有分配的区域,并且第一个指针存储在PEB结构中,因此用户空间和内核空间代码都知道已分配的堆池。在存储器的连续片段