定长内存池介绍
定长内存池就是一个固定内存申请或释放大小的内存池,其特点是:①性能达到极致。②不需要考虑内存碎片问题。
①性能达到极致:由于内存池中的内存块大小一致,内存申请和释放操作通常只需要从池中取出或归还相应大小的内存块即可,避免了频繁的系统调用(如malloc和free),从而在一定程度上提高了内存管理效率,特别是在大量进行小对象内存分配和回收的场景下,性能优势更为明显。
②不需要考虑内存碎片问题:因为内存池中的所有内存块大小相同,在分配和回收过程中不会产生不同大小的内存空洞,因此能够有效减少内存碎片。
定长内存池的实现思想
向系统申请一大块内存,使用一个指针指向内存,每次申请,就从这块内存中拿一块固定大小的内存(4字节或8字节,按32位系统或64位系统)。当使用者释放内存时,直接使用一个自由链表,将这一块块内存使用头插的形式连接起来,进行管理,当后续需要申请内存时,可以在自由链表上取内存块。
细节问题
1.获取系统下指针的大小用于链表链接
由于使用链表将还回来的内存管理,因此每一块内存至少需要4字节或者8字节,那么如果申请的内存 小于4字节或者8字节就不好进行管理了,而如果使用64位系统,指针的大小是8字节。
因此需要保证的是在32位系统下,内存块要大于4字节,64位系统下,要大于8字节。因此需要将内存对象强转为二级指 针,再解引用。比如(*(void**)),这样就是获取到当前系统下指针的大小。
2.内存申请释放问题
当一块内存块用完,需要再开辟的时候,其判断条件是当前的对象类型的大小,是否大于内存池剩余内存的大小,如果是,那么需要再向系统申请一大块内存。如果不是,则直接分配给使用者。
其次,当自由链表中有内存了,那么申请内存的时候,直接从自由链表中申请。
最后,需要显示调用对象的构造函数和析构函数。
代码实现
向堆申请内存
既然自己动手实现内存池,脱离malloc和new了,就直接使用Windows提供的原生库函数。
LPVOID VirtualAlloc(
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flAllocationType,
DWORD flProtect
);
//lpAddress:指定分配内存的起始地址。如果