代码
#include <stdio.h>
#include<windows.h>
void main()
{
HLOCAL h1,h2,h3,h4;
HANDLE hp;
hp = HeapCreate(0,0,0);
__asm int 3
h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8);
h2 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8);
h3 = HeapAlloc(hp,HEAP_ZERO_MEMORY,16);
h4 = HeapAlloc(hp,HEAP_ZERO_MEMORY,24);
__asm int 3
HeapFree(hp,0,h1);
HeapFree(hp,0,h2);
HeapFree(hp,0,h3);
HeapFree(hp,0,h4);
__asm int 3
h2 = HeapAlloc(hp,HEAP_ZERO_MEMORY,16);
__asm int 3
HeapFree(hp,0,h2);
__asm int 3
h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8);
__asm int 3
}
PS:堆是可扩展的时候快表才会启用,要想启用快表我们在创建堆的时候就不能使用 HeapCreate(0,0x1000,0x10000)来创建堆了,而要使HeapCreate(0,0,0)创建一个可扩展的堆。
实验目的
简单理解快表
实验准备
环境:windows xp
编译器:vc++
调试器:OD
实验过程
1.打开程序崩溃后用OD调试,发现堆块还是建立在老地方0x003A0000
2.观察与之前的空表有什么不同。
首先发现尾块的位置更靠后了,之前只有空表的尾块是位于0x003a0688,而现在加了快表之后位置变成了0x003a1e90。而之前尾块的地方现在则就变成了快表。
快表与空表空的时候不一样,快变里面是空的,而空表里面装了自己的地址。
2.把int 3移到HeapAlloc后面。观察到了堆表已经建在0x3a1e88的位置了,和上一节基本一样。
3.再把int 3移到HeapFree的后面,观察前面的快表,发现快表1,2,3表头都填充进了地址.(快表未满时优先释放到快表中)
再观察指向的h1,h2,h3,h4,发现Lookaside[1]指向h2,而h2中的指针又指向h1,组成了一串单向链表,Lookaside[2]指向h3,Lookaside[3]指向h4。指向的地址都自动跳过了堆块头的8个字节。
8字节的都链入Lookaside[1],16字节的都链入Lookaside[2],依次类推。直到四个快表都被填充完。
同时还发现快表中的Flag位都为1,也就是都是占用态。而空表Free了就都是空闲态了。
4.再把int 3放在下一个地方,发现因为申请了16字节的空间,系统就把Lookaside[2]指向的h2分配给我们了,同时Lookaside[2]前面的地址就变为NULL。
5,把int 3再移到下一个位置,发现申请的话操作也基本相仿,就是Lookaside[2]前面的地址又分配进去了
6.又把int 3移到下一个位置。这里申请了8字节的内存,观察快表发现没有什么明显的变化。
再看看下面的堆块,发现之前h2指向h1的指针已经变为NULL了,证明h2现在已经被拆卸下来了。