天天看点

软件调试23章 堆管理器向内存管理器释放的疑惑

    张银奎老师的<软件调试>第23章提到可以用windbg !heap -v HeapHandle来查看堆解除提交的粒度。我在win7 32bit机器上测试系统堆解除提交的情况,得到了不同的结果。

    首先我的系统堆地址是0x360000:

0:001> !heap -a
Index   Address  Name      Debugging options enabled
  1:   00360000 
    Segment at 00360000 to 00460000 (00028000 bytes committed)
  2:   00010000  - heap headers inaccessible, skipping
  3:   00020000  - heap headers inaccessible, skipping
  4:   00320000 
    Segment at 00320000 to 00330000 (00005000 bytes committed)      

    系统堆解除提交的粒度是0x2000,因此0x2000*8=0x10000=65536B,即堆上有64KB的空闲内存就会释放内存。

0:001> !heap -v 0x00360000 
Index   Address  Name      Debugging options enabled
  1:   00360000 
    Segment at 00360000 to 00460000 (00028000 bytes committed)
    Flags:                00000002
    ForceFlags:           00000000
    Granularity:          8 bytes
    Segment Reserve:      00100000
    Segment Commit:       00002000
    DeCommit Block Thres: 00000800
    DeCommit Total Thres: 00002000
    Total Free Size:      000003ad      
软件调试23章 堆管理器向内存管理器释放的疑惑
软件调试23章 堆管理器向内存管理器释放的疑惑
软件调试23章 堆管理器向内存管理器释放的疑惑

3张图依次是分配堆块前,分配后,释放后,程序在任务管理器中显示的vm大小。

可以看到分配和释放前后,vm的大小没有改变。

这就很奇怪了,我不断尝试增加申请和释放的堆内存数量,直到分配释放的堆内存数量接近512KB时候,在任务管理器中有明显的decommit动作。

软件调试23章 堆管理器向内存管理器释放的疑惑
软件调试23章 堆管理器向内存管理器释放的疑惑
软件调试23章 堆管理器向内存管理器释放的疑惑

最后,我查看peb中关于堆释放的粒度总算找到了解释这个疑惑的点:

0:001> dt _peb @$peb
HiHeapVC8!_PEB
   +0x080 HeapDeCommitTotalFreeThreshold : 0x10000
   +0x084 HeapDeCommitFreeBlockThreshold : 0x1000      

继续阅读