29.windbg-!heap(堆状态)

来源:互联网 发布:java面向切面编程 编辑:程序博客网 时间:2024/06/05 09:28

以下以windbg启动calc为调试结果:

!heap

!heap 扩展显示堆使用信息,控制堆管理器中的断点,检测泄露的堆块,搜索堆块或者显示页堆(page heap)信息。

!heap -h列出当前进程的所有堆:

0:000> !heap -hIndex   Address  Name      Debugging options enabled  1:   000a0000     Segment at 000a0000 to 001a0000 (00003000 bytes committed)  2:   001a0000     Segment at 001a0000 to 001b0000 (00006000 bytes committed)  3:   001b0000     Segment at 001b0000 to 001c0000 (00003000 bytes committed)


!heap -v可以观察堆的分配粒度和解除提交阈值:

0:000> !heap 000a0000 -vIndex   Address  Name      Debugging options enabled  1:   000a0000     Segment at 000a0000 to 001a0000 (00003000 bytes committed)    Flags:                50000062    ForceFlags:           40000060    Granularity:          8 bytes    Segment Reserve:      00100000    Segment Commit:       00002000    DeCommit Block Thres: 00000200    DeCommit Total Thres: 00002000    Total Free Size:      000000d1    Max. Allocation Size: 7ffdefff    Lock Variable at:     000a0608    Next TagIndex:        0000    Maximum TagIndex:     0000    Tag Entries:          00000000    PsuedoTag Entries:    00000000    Virtual Alloc List:   000a0050    UCR FreeList:        000a0598    FreeList Usage:      00000000 00000000 00000000 00000000    FreeList[ 00 ] at 000a0178: 000a2980 . 000a2980   (1 block )

Segment at 000a0000 to 001a0000 (00003000 bytes committed)指明堆的内存范围和提交字节数
Granularity: 8 bytes指明堆块分配粒度

 

由于堆管理器使用HEAP结构来记录和维护堆的管理信息,因此我们把这个结构称为堆的管理结构,因为这个结构总是在每个堆的开始处,因此有时也被称为堆的头结构

下面显示了_HEAP的结构:

:000> dt ntdll!_HEAP 000a0000    +0x000 Entry            : _HEAP_ENTRY   +0x008 Signature        : 0xeeffeeff   +0x00c Flags            : 0x50000062   +0x010 ForceFlags       : 0x40000060   +0x014 VirtualMemoryThreshold : 0xfe00   +0x018 SegmentReserve   : 0x100000   +0x01c SegmentCommit    : 0x2000   +0x020 DeCommitFreeBlockThreshold : 0x200   +0x024 DeCommitTotalFreeThreshold : 0x2000   +0x028 TotalFreeSize    : 0xd1   +0x02c MaximumAllocationSize : 0x7ffdefff   +0x030 ProcessHeapsListIndex : 1   +0x032 HeaderValidateLength : 0x608   +0x034 HeaderValidateCopy : (null)    +0x038 NextAvailableTagIndex : 0   +0x03a MaximumTagIndex  : 0   +0x03c TagEntries       : (null)    +0x040 UCRSegments      : (null)    +0x044 UnusedUnCommittedRanges : 0x000a0598 _HEAP_UNCOMMMTTED_RANGE   +0x048 AlignRound       : 0x17   +0x04c AlignMask        : 0xfffffff8   +0x050 VirtualAllocdBlocks : _LIST_ENTRY [ 0xa0050 - 0xa0050 ]   +0x058 Segments         : [64] 0x000a0640 _HEAP_SEGMENT   +0x158 u                : __unnamed   +0x168 u2               : __unnamed   +0x16a AllocatorBackTraceIndex : 0   +0x16c NonDedicatedListLength : 1   +0x170 LargeBlocksIndex : (null)    +0x174 PseudoTagEntries : (null)    +0x178 FreeLists        : [128] _LIST_ENTRY [ 0xa2980 - 0xa2980 ]   +0x578 LockVariable     : 0x000a0608 _HEAP_LOCK   +0x57c CommitRoutine    : (null)    +0x580 FrontEndHeap     : 0x000a0688    +0x584 FrontHeapLockCount : 0   +0x586 FrontEndHeapType : 0x1 ''   +0x587 LastSegmentIndex : 0 ''

Segments字段用来记录堆中包含的所有段,它是一个数组,每个元素都指向一个HEAP_SEGMENT结构的指针,

   +0x058 Segments         : [64] 0x000a0640 _HEAP_SEGMENT

LastSegmentIndex的值加1就是段的总个数:

 +0x587 LastSegmentIndex : 0 ''

说明就一个段:

0:000> dt _HEAP_SEGMENT  0x000a0640 ntdll!_HEAP_SEGMENT   +0x000 Entry            : _HEAP_ENTRY   +0x008 Signature        : 0xffeeffee   +0x00c Flags            : 0   +0x010 Heap             : 0x000a0000 _HEAP   +0x014 LargestUnCommittedRange : 0xfd000   +0x018 BaseAddress      : 0x000a0000    +0x01c NumberOfPages    : 0x100   +0x020 FirstEntry       : 0x000a0680 _HEAP_ENTRY//第一个堆块   +0x024 LastValidEntry   : 0x001a0000 _HEAP_ENTRY   +0x028 NumberOfUnCommittedPages : 0xfd   +0x02c NumberOfUnCommittedRanges : 1   +0x030 UnCommittedRanges : 0x000a0588 _HEAP_UNCOMMMTTED_RANGE   +0x034 AllocatorBackTraceIndex : 0   +0x036 Reserved         : 0   +0x038 LastEntryInSegment : 0x000a2978 _HEAP_ENTRY//最后一个堆块


 堆管理器使用_HEAP_ENTRY来描述每个堆块:

0:000> dt _HEAP_ENTRY 0x000a0680 ntdll!_HEAP_ENTRY   +0x000 Size             : 0x303//堆块的大小,以分配粒度为单位   +0x002 PreviousSize     : 8//前一个堆块的大小   +0x000 SubSegmentCode   : 0x00080303    +0x004 SmallTagIndex    : 0x60 '`'   +0x005 Flags            : 0x7 ''//标志   +0x006 UnusedBytes      : 0x18 ''//因为补齐而多分配的字节数   +0x007 SegmentIndex     : 0 ''//这个堆块所在段的序号

其中Flags字段代表堆块的状态,其值是下列标志位的组合

标志值含义HEAP_ENTRY_BUSY01该块处于占用状态HEAP_ENTRY_EXTRA_PRESENT02该块存在额外的描述HEAP_ENTRY_FILL_PATTERN04使用固定模式填充堆块HEAP_ENTRY_VIRTUAL_ALLOC08虚拟分配HEAP_ENTRY_LAST_ENTRY0X10这是该段的最后一个块
_HEAP_ENTRY的长度固定为8字节长,位于堆块起始处,其后便是堆块的用户数据,也就是说,把HeapAlloc函数

返回的地址减去8,就是这个堆块的_HEAP_ENTRY结构的地址

 



 



 

原创粉丝点击