C++内存池的实现

来源:互联网 发布:广州软件开发公司排名 编辑:程序博客网 时间:2024/06/05 14:45

自己也尝试了很多方法才实现,有耐心看下去会有帮助的

一、为什么使用内存池

1、在没有使用内存池的程序中如果频繁的分配、释放内存,会造成内存碎片。可能会导致程序崩溃。2、使用系统的malloc、free 或者 new delete 频繁的分配内存效率是非常低的。特别在服务器程序中,处理大量客户端请求,是非常消耗性能的。3、内存不容易管理

二、内存池的实现

内存模型

上图是一个内存池模型, 总共分成了4个区域。

这里简单介绍一下这4个区域:

  1. 黑色区域主要用来记录其他3个区域的内存地址信息和内存使用情况
  2. 灰色区域是内存节点,用来索引绿色区域(可使用内存)的内容
  3. 蓝色区域是用来记录用户已经使用的内存块和已经使用的内存块
  4. 绿色区域是真正可分配给用户使用的内存

1、黑色区域对应的结构体信息

// 内存池typedef struct MemoryPoll{    PMEMORYCHUNK pmemory_chunk_list_poll;   // 内存块链表节点    PMEMORYCHUNK pmemory_chunk_free_list;   // 空闲块链表    PMEMORYBLOCK pmemory_block_head;        // block头    void *pbuffer; // 分配的内存开始    unsigned block_size; // 内存块数量    unsigned used_size;  // 已经使用的大小}MEMORYPOLL, *PMEMORYPOLL;

图解:
这里写图片描述

这里解释了: pbuffer, block_size, used_size这三个字段的意思剩下的三个字段等后面两个区域介绍完之后再详细解释

pmemory_block_head 是指向灰色区域的开始地址

2、灰色区域, 蓝色区域(内存池的要点)

// 一个内存节点(小块)typedef struct MemoryBlock{    MemoryChunk *pmemory_chunk; // 属于哪个内存块}MEMORYBLOCK, * PMEMORYBLOCK;// 分配的内存块结构typedef struct MemoryChunk // 分配的内存块{    unsigned count; // 节点的数量    struct MemoryBlock *pmemory_block_head; // 内存节点头    struct MemoryChunk *pPrev; // 上一个内存块    struct MemoryChunk *pNext; // 下一个内存块    bool bUse;}MEMORYCHUNK,* PMEMORYCHUNK;

我们绿色区域的可分配内存是按照节点来分配的, 如果不足一个节点的倍数就调整到一个节点的倍数
比如:
一个节点的大小是 64字节, 用户请求一个100字节的大小,因为不足2个节点的大小,但是大于1个节点的大小,会调整到128字节

蓝色区域是记录着已经分配的内存块和空闲的内存块, 是一个双向链表的结构

当我们分配一块内存的时候,会划分出一块区域来记录分配和没分配的内存信息,这块区域有多大呢?
比如用户请求1024字节来当做内存池

unsigned size = 1024;size = size - sizeof(MemoryPoll); // 大小减去黑色区域的大小// 下面就可以结算出这块内存可以使用多大的内存结构/* BLOCKSIZE(一个节点分配的大小) + MemoryBlock(灰色区域) + MemoryChunk(内存块)    这三个加起来就是一个可分配节点需要占用的大小    MemoryChunk 是已最大化分配的    假设用户只分配一个节点的大小,那MemoryChunk里面就只包含一个MemoryBlock的数量    所以MemoryChunk最坏的情况数量是和最大的内存节点的数量是一样的*/unsigned block_size = size / (sizeof(MemoryBlock) + sizeof(MemoryChunk) + BLOCKSIZE);

最终图解:

0 0