目录
一、实验环境
操作系统:windows 2000 professional
软件:ollydbg原版、vc++6.0
!!!将OD设置为实时调试器!!!
VC++6.0 build版本:release版本(默认Debug版本)
二、实验代码
#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);
HeapFree(hp,0,h1);
HeapFree(hp,0,h2);
HeapFree(hp,0,h3);
HeapFree(hp,0,h4);
h2 = HeapAlloc(hp,HEAP_ZERO_MEMORY,16);
HeapFree(hp,0,h2);
}
三、实验步骤
1、内存申请(与快表没关)
编译后,OD直接运行到int 3处,在数据窗口查看偏移地址为0x178处(0x178开始为空表索引区),可以看到尾块的地址已经不在是0x360688,而变成了0x361E90。
注:原来的0x360688位置被块表“霸占”。
在数据窗口跳转到0x361E90位置,发现了“尾块”。
F8执行完所有的内存申请请求,在0x361E90处可见已申请的堆块h1、h2、h3和h4。
注:因为初始状态快表为空,且空表中只有free[0]指向一个大块,所以就算是小块内存申请,也只会执行“次优块”分配。因此,申请的h1、h2、h3和h4只会以从“尾块中割一部分空间”的形式获取内存。
数据窗口跳转到0x360688处,可以发现快表中是空的,没有链接任何一个空闲块。
2、内存释放(与快表有关)
代码释放掉h1、h2,在数据窗口中查看lookaside[1]的情况,可以发现,lookaside[1]指向0x361EA0(h2处)。
解释:
(1)为什么被释放的块会链入快表?
因为快表的存在,被释放的空闲块(小块)会被优先链入快表中,只有快表满了,才会链入空表中,所以被释放h1、h2会链入lookaside[2]。
(2)为什么lookaside[2]指向h2(0x361EA0)?
其实这里,在释放h1时,lookaside[2]会指向h1(0x361E90),只是在释放h2时,采用头插法使得lookaside[2]指向h2,h2指向h1。
数据窗口跳转到0x361EA0,可见h1、h2的具体情况。
释放剩余的h3、h4,在快表索引区(0x360688)处,可以看到h3、h4也分别链入了快表lookaside[3]、lookaside[4]。
3、内存申请(与快表有关)
执行新的h2申请,可见lookaside[3]处地址指针已经清空。
4、内存释放(与快表有关)
释放掉新申请的h2,lookaside[3]重新指回0x361EB0.
注:我觉得《0day》原书中关于快表的实验部分,有点错误!0x360688开始应该是lookaside[0],它原书lookaside[0]位于0x3606B8处。如果原书没错,难道释放的时候,根据块身的大小链入快表的哪一项?