不可增长堆中的0x7FFF8大小限制

  Finally,还是找到了这个让人"pleasure and pain"的问题的答案!

 

  当在程序中使用HeapCreate()函数来创建私有堆的时候,其中有个诡异的参数——dwMaximumSize,当它指定为0时(我们很高兴),它为可增长堆(growable heap),当它指定为正整数时(-_-),它为不可增长堆(non-growable heap)。

  查看MSDN中关于该函数的解释,当dwMaximumSize为非零时,好了,有一句让人费解的话出现了:However, the heap cannot grow, so the maximum size of a memory block in the heap is a bit less than 0x7FFF8 bytes. Requests to allocate larger blocks fail, even if the maximum size of the heap is large enough to contain the block.(然而,这个堆是不可增长的,所以在此堆中一个内存块的最大尺寸应该比0x7FFF8小一些,若在此堆中分配比这更大的内存块,即使堆的最大尺寸足够容纳这个内存块,也不会成功!)

  在不可增长堆的一次性分配的内存块尺寸不能超过0x7FFF8,为什么? Baidu,Google,...,nothing!

  答案就在堆的实现上,堆管理器(Heap Manager)中的后端管理器。

  后端管理器中有个自由列表(free lists),如下图所示:

其中,index1--无用,index2--16B(8B用户请求内存+8B元数据),index3--24B,...,index127--1016B(1008B+8B),从index2到index127所对应的链表用来存放固定大小的自由堆块。

index0用来存放可变大小的自由堆块,其大小范围从1024B(1016B用户请求数据+8B元数据)到0x7FFF8(0x7FFF0用户请求数据+8B),并且从小到大排列(效率较高)。

 

整个堆的内存是从虚拟内存管理器中分配的(VirtualAlloc()之类),可增长堆与不可增长堆的区别在于:不可增长堆初始化的时候,一旦被预订了指定的内存空间(由HeapCreate的dwMaximumSize参数指定)后,那么无论怎样,它将不会再次请求虚拟内存管理器为之分配内存。而可增长堆是可以的。

 

当程序需要在堆中分配>=0x7FFF8时,由于在index0所对应的列表中也找不到如此大的内存块,那么堆管理器将尝试请求虚拟内存管理器为之分配大块内存。但不可增长堆是无法再次请求虚拟内存管理器的,所以即使堆中的自由堆块总和能容纳所请求的内存块,也无法为之分配

合适的自由堆块。

 

0x7FFF8就是一个设计堆时的限制,仅此而已……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值