searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

一种内存池的实现方案

2023-10-17 07:42:43
9
0

一、背景

C/C++下内存管理是程序开发过程中需要重点关注的问题,如分配足够的内存、追踪内存的分配、在不需要的时候释放内存。而直接使用系统调用malloc/free、new/delete进行内存分配和释放,有以下弊端:

  1. 调用malloc/new,系统需要根据“最先匹配”、“最优匹配”或其他算法在内存空闲块表中查找一块空闲内存,调用free/delete,系统可能需要合并空闲内存块,这些会产生额外开销
  2. 频繁使用时会产生大量内存碎片,从而降低程序运行效率
  3. 容易造成内存泄漏

内存池(memory pool)是代替直接调用malloc/free、new/delete进行内存管理的常用方法,当我们申请内存空间时,首先到我们的内存池中查找合适的内存块,而不是直接向操作系统申请,优势在于:

  1. 比malloc/free进行内存申请/释放的方式快
  2. 不会产生或很少产生堆碎片
  3. 可避免内存泄漏

  

二、内存池实现方案

首先给出该方案的整体架构,如下:

图1 内存池架构图

结构中主要包含block、list 和pool这三个结构体,block结构包含指向实际内存空间的指针,前向和后向指针让block能够组成双向链表;list结构中free指针指向空闲 内存块组成的链表,used指针指向程序使用中的内存块组成的链表,size值为内存块的大小,list之间组成单向链表;pool结构记录list链表的头和尾。

 

三、方案策略

  1. 内存跟踪策略

该方案中,在进行内存分配时,将多申请12个字节,即实际申请的内存大小为所需内存大小+12。在多申请的12个字节中,分别存放对应的list指针(4字节)、used指针(4字节)和校验码(4字节)。通过这样设定,我们很容易得到该块内存所在的list和block,校验码起到粗略检查是否出错的作用。该结构图示如下:

图2 内存块申请示意图

图中箭头指示的位置为内存块真正开始的位置。

 

  1. 内存申请和释放策略

申请:根据所申请内存的大小,遍历list链表,查看是否存在相匹配的size;

    存在匹配size:查看free时候为NULL

      free为NULL:使用malloc/new申请内存,并将其置于used所指链表的尾部

      free不为NULL:将free所指链表的头结点移除,放置于used所指链表的尾部

    不存在匹配size:新建list,使用malloc/new申请内存,并将其置于该list的used所指链表尾部

   返回内存空间指针

释放:根据内存跟踪策略,获取list指针和used指针,将其从used指针所指的链表中删除,放置于free指针所指向的链表

 

四、方案特点

该方案有以下特点:

  1. 程序启动后内存池并没有内存块,到程序真正进行内存申请和释放的时候才接管内存块管理;
  2. 该内存池对到来的申请,对申请大小并不做限制,其为每个size值创建链表进行内存管理;
  3. 该方案没有提供限定内存池大小的功能

结合分析,可以得出该方案应用场景如下:程序所申请的内存块大小比较固定(比如只申请/释放1024bytes或2048bytes的内存),申请和释放的频率基本保持一致(因申请多而释放少会占用过多内存,最终导致系统崩溃)。

 

0条评论
0 / 1000
w****n
8文章数
0粉丝数
w****n
8 文章 | 0 粉丝
原创

一种内存池的实现方案

2023-10-17 07:42:43
9
0

一、背景

C/C++下内存管理是程序开发过程中需要重点关注的问题,如分配足够的内存、追踪内存的分配、在不需要的时候释放内存。而直接使用系统调用malloc/free、new/delete进行内存分配和释放,有以下弊端:

  1. 调用malloc/new,系统需要根据“最先匹配”、“最优匹配”或其他算法在内存空闲块表中查找一块空闲内存,调用free/delete,系统可能需要合并空闲内存块,这些会产生额外开销
  2. 频繁使用时会产生大量内存碎片,从而降低程序运行效率
  3. 容易造成内存泄漏

内存池(memory pool)是代替直接调用malloc/free、new/delete进行内存管理的常用方法,当我们申请内存空间时,首先到我们的内存池中查找合适的内存块,而不是直接向操作系统申请,优势在于:

  1. 比malloc/free进行内存申请/释放的方式快
  2. 不会产生或很少产生堆碎片
  3. 可避免内存泄漏

  

二、内存池实现方案

首先给出该方案的整体架构,如下:

图1 内存池架构图

结构中主要包含block、list 和pool这三个结构体,block结构包含指向实际内存空间的指针,前向和后向指针让block能够组成双向链表;list结构中free指针指向空闲 内存块组成的链表,used指针指向程序使用中的内存块组成的链表,size值为内存块的大小,list之间组成单向链表;pool结构记录list链表的头和尾。

 

三、方案策略

  1. 内存跟踪策略

该方案中,在进行内存分配时,将多申请12个字节,即实际申请的内存大小为所需内存大小+12。在多申请的12个字节中,分别存放对应的list指针(4字节)、used指针(4字节)和校验码(4字节)。通过这样设定,我们很容易得到该块内存所在的list和block,校验码起到粗略检查是否出错的作用。该结构图示如下:

图2 内存块申请示意图

图中箭头指示的位置为内存块真正开始的位置。

 

  1. 内存申请和释放策略

申请:根据所申请内存的大小,遍历list链表,查看是否存在相匹配的size;

    存在匹配size:查看free时候为NULL

      free为NULL:使用malloc/new申请内存,并将其置于used所指链表的尾部

      free不为NULL:将free所指链表的头结点移除,放置于used所指链表的尾部

    不存在匹配size:新建list,使用malloc/new申请内存,并将其置于该list的used所指链表尾部

   返回内存空间指针

释放:根据内存跟踪策略,获取list指针和used指针,将其从used指针所指的链表中删除,放置于free指针所指向的链表

 

四、方案特点

该方案有以下特点:

  1. 程序启动后内存池并没有内存块,到程序真正进行内存申请和释放的时候才接管内存块管理;
  2. 该内存池对到来的申请,对申请大小并不做限制,其为每个size值创建链表进行内存管理;
  3. 该方案没有提供限定内存池大小的功能

结合分析,可以得出该方案应用场景如下:程序所申请的内存块大小比较固定(比如只申请/释放1024bytes或2048bytes的内存),申请和释放的频率基本保持一致(因申请多而释放少会占用过多内存,最终导致系统崩溃)。

 

文章来自个人专栏
技术原理与方案
8 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0