1、内存池简介
内存池是池化技术中的一种形式。通常我们在编写程序的时候回使用 new delete 这些关键字来向操作系统申请内存,而这样造成的后果就是每次申请内存和释放内存的时候,都需要和操作系统的系统调用打交道,从堆中分配所需的内存。如果这样的操作太过频繁,就会找成大量的内存碎片进而降低内存的分配性能,甚至出现内存分配失败的情况。而内存池就是为了解决这个问题而产生的一种技术。从内存分配的概念上看,内存申请无非就是向内存分配方索要一个指针,当向操作系统申请内存时,操作系统需要进行复杂的内存管理调度之后,才能正确的分配出一个相应的指针。而这个分配的过程中,我们还面临着分配失败的风险。所以,每一次进行内存分配,就会消耗一次分配内存的时间,设这个时间为 T,那么进行 n 次分配总共消耗的时间就是 nT;如果我们一开始就确定好我们可能需要多少内存,那么在最初的时候就分配好这样的一块内存区域,当我们需要内存的时候,直接从这块已经分配好的内存中使用即可,那么总共需要的分配时间仅仅只有 T。当 n 越大时,节约的时间就越多。


如上面两张图,一个内存池由若干个内存块组成,一个内存块由若干个内存单元组成(即链表节点)。

2、内存池的代码实现
内存池类MemoryPool的声明如下:

//MemoryPool.h
#pragma once
#include <iostream>
using namespace std;
template<int ObjectSize, int NumofObjects = 20>
class MemPool
{
private://空闲节点结构体struct FreeNode{FreeNode* pNext;       //指向下一个空闲节点的指针char data[ObjectSize]; //节点内容};//内存块结构体struct MemBlock{MemBlock* pNext;            //指向下一个内存块的指针int nFree;                  //该内存块空闲节点的数量FreeNode data[NumofObjects];//内存节点数组FreeNode* freeNodeHeader;   //空闲节点头指针};
public:MemPool(){freeNodeHeader = NULL;memBlockHeader = NULL;}~MemPool(){MemBlock* ptr;while (memBlockHeader) //删除所有的空闲块指针{ptr = memBlockHeader->pNext;delete memBlockHeader;memBlockHeader = ptr;}}void* malloc();          //向内存池申请内存void free(void*);        //从内存池释放内存
private:MemBlock* memBlockHeader; //空闲内存块头指针
};

内存池类MemoryPool的实现如下:

//MemoryPool.cpp
#include"MemoryPool.h"
//分配空闲的节点
template<int ObjectSize, int NumofObjects>
void* MemPool<ObjectSize, NumofObjects>::malloc()
{void* freeNode;if (!memBlockHeader){//内存池当前内存块链表为空,说明是第一次内存申请MemBlock* newBlock = new MemBlock;     //分配新的内存块,即分配20个内存单元newBlock->pNext = NULL;                //无下一个空闲块newBlock->nFree = NumofObjects;        //空闲节点数量memBlockHeader = newBlock;             //空闲块头指针freeNodeHeader= &newBlock->data[0];    //设置内存块的第一个节点为空闲节点链表的首节点//将内存块的其它节点串起来(初始化内存块)for (int i = 1; i < NumofObjects; ++i){newBlock->data[i - 1].pNext = &newBlock->data[i];}newBlock->data[NumofObjects - 1].pNext = NULL;}MemBlock *myBlock = memBlockHeader;        //当前内存块为内存块头链表指针指向的内存块while (myBlock &&!myBlock->nFree)          //寻找有空闲节点的内存块myBlock = myBlock->pNext;              //继续在下一个空闲块中查找if (myBlock){//存在有空闲节点的内存块memBlockHeader = myBlock;             //更新空闲块头指针}else{//当前不存在有空闲节点的内存块,需要再次申请分配内存MemBlock* newBlock = new MemBlock;     //分配新的内存块,即分配20个内存单元newBlock->nFree = NumofObjects;        //空闲节点数量freeNodeHeader = &newBlock->data[0];   //设置内存块的第一个节点为空闲节点链表的首节点//将内存块的其它节点串起来(初始化内存块)for (int i = 1; i < NumofObjects; ++i){newBlock->data[i - 1].pNext = &newBlock->data[i];}newBlock->data[NumofObjects - 1].pNext = NULL;//将新内存块加入到内存块链表newBlock->pNext = memBlockHeader;   //头插法memBlockHeader = newBlock;}//返回空节点闲链表的第一个节点void* freeNode = freeNodeHeader;freeNodeHeader = freeNodeHeader->pNext;memBlockHeader->nFree--;               //当前内存块空闲内存节点减一   return freeNode;
}
//释放已经分配的节点
template<int ObjectSize, int NumofObjects>
void MemPool<ObjectSize, NumofObjects>::free(void* p)
{MemoryBlock* pMyBlock = memBlockHeader;bool bIsExist = false;//判断p是否属于内存池while (pMyBlock){bIsExist = false;for (int i = 0; i < NumofObjects; i++){if (p == pMyBlock->newBlock->data[i]){bIsExist = true;break;}}if (bIsExist)break;pMyBlock = pMyBlock->pNext;}if (!bIsExist)//p不属于线程池delete p; //将其回收给进程堆else{FreeNode* pNode = (FreeNode*)p;pNode->pNext = freeNodeHeader; //将释放的节点插入空闲节点头部pNode->nFree--;                 //该内存块空闲节点数量减1freeNodeHeader = pNode;}
}

3、参考资源
C++ 应用程序性能优化,第 6 章:内存池:
https://www.ibm.com/developerworks/cn/linux/l-cn-ppp/index6.html
C++ 内存池介绍与经典内存池的实现:
https://blog.csdn.net/K346K346/article/details/49538975?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase

内存池:申请内存与释放内存相关推荐

  1. android内存池,两种常见的内存管理方法:堆和内存池

    描述 本文导读 在程序运行过程中,可能产生一些数据,例如,串口接收的数据,ADC采集的数据.若需将数据存储在内存中,以便进一步运算.处理,则应为其分配合适的内存空间,数据处理完毕后,再释放相应的内存空 ...

  2. 任意大小 内存池 c语言,C语言内存池使用模型-1 - Mr.南柯 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...

    Mo2m4C;i$ZE0在用C语言开发时,特别是在服务器端,内存的使用会成为系统性能的一个瓶颈,如频繁的分配和释放内存,会不断的增加系统的内存碎片,影响内核之 后分配内存的效率,这个时候一个比较可行的 ...

  3. 内存池、自由空间、堆内存 等名称解释(不间断更新。。。)

    简单说说几个名词解释:(c++ primer 第五版) 1. 内存池.自由空间.堆内存 其实是同一种概念的不同叫法. 编译器分配的内存,一般在全局存储区,要么在栈内存等. 堆内存,是程序员自己分配的内 ...

  4. python内存池机制,python基础—12python内存管理机制

    一.内存池机制 1.对象池 面试题目: python内存管理机制是什么? 1). 由于python中万物皆对象,内存管理机制就是对象的存储问题,Python会分 配一块内存空间去存储对象. 2) 对于 ...

  5. HM 内存池设计(2) HM6.0内存池设计

    用于HM6.0代码中的内存池. 相对于(1)的改进: a.chunk的大小从64bytes开始,到64KB.max_free_chunk[MAX_INDEX] 表示各个size的数目. const u ...

  6. php的内存划分,解析PHP中的内存管理,PHP动态分配和释放内存

    摘要 内存管理对于长期运行的程序,例如服务器守护程序,是相当重要的影响:因此,理解PHP是如何分配与释放内存的对于创建这类程序极为重要.本文将重点探讨PHP的内存管理问题. 一. 内存 在PHP中,填 ...

  7. 如何手动释放linux内存的方法,centos手动释放内存的方法

    CentOS 是一个基于Red Hat Linux 提供的可自由使用源代码的企业级Linux发行版本.每个版本的 CentOS都会获得十年的支持(通过安全更新方式).接下来是小编为大家收集的cento ...

  8. 动态内存的申请和非动态内存的申请_深圳罗湖“限制非深户申请公办学位”惹争议,官方权威回应来了...

    每年的学位申请 对家长来说就像一场比赛 要操心的事情实在太多了!  比如:今年我家孩子会不会无学可上? 而昨天一则通告则是将在罗湖的家长们急坏了 ▼ 昨日(1月7日),深圳罗湖区教育局发布<罗湖 ...

  9. 动态内存的申请和非动态内存的申请_公安交管新举措咋解读?非营运七座车6年免检,70岁可申请驾照...

    齐鲁晚报·齐鲁壹点记者张泰来 机动车免检范围扩容,除了6座非营运小型客车,7至9座非营运小微型客车(面包车除外)纳入六年免检范围:摩托车驾照全国通考:小型车辆.轻便摩托车驾照申领取消年龄限制.22日, ...

  10. 动态内存的申请和非动态内存的申请_非深户父母买社保就加分!深圳罗湖学位申请规则将调整!快算算你多少分...

    前几天宝安公示了 新年的学位入学规则调整方案 很多人在问福田区.罗湖区 南山区的有没有...... 今天,罗湖区义务教育学位 申请分类和积分办法修订稿也进行了公示 本次修订主要是根据 计划生育政策改变 ...

最新文章

  1. python深拷贝和浅拷贝的使用场景_深拷贝、浅拷贝的理解与使用场景
  2. chosen ajax获取数据,Jquery Chosen插件 - 由Ajax动态填充列表
  3. Python进阶03 模块
  4. OPPM 一页纸项目管理 One-Page Project Management
  5. sqlserver2005仅当使用了列的列表,并且 IDENTITY_INSERT 为 ON 时,才能在表 'SendMealAddress'中为标识列指定显式值。...
  6. 前端学习(2996):vue+element今日头条管理--代码测试规范
  7. Swift中文教程(一)基础数据类型
  8. 为Pokémon Go而生的聊天软件GoChat,坐拥百万用户却快要破产
  9. Linux合入patch命令,Linux下Patch命令用来打补丁和卸载补丁
  10. kibana更改时间显示格式
  11. Matplotlib:初学者绕不开的库,详解50种常用可视化图表!
  12. Java实现读取csv文件
  13. open sl java audio_webrtc学习(二): audio_device之opensles
  14. gif图像分解、gif图像制作
  15. 【产业互联网周报】奇安信科创板IPO过会;声网Agora登陆纳斯达克;国产光刻机双工件台供应商华卓精科科创板IPO获受理...
  16. 使用Matlab/Simulink进行电力电子控制设计
  17. 基于Java+Spring的图书管理系统详细设计和实现
  18. 高通滤波器与低通滤波器
  19. 使用Git来管理svn代码
  20. iptables日志管理

热门文章

  1. netty 简单demo
  2. 一劳永逸去除Word文档修订和批注帮助
  3. 请和我一起学习机器学习算法(决策树)
  4. 一些概念DRX DTX SFN MFN。
  5. 前台开发总结13——20180419
  6. Pandas+Pyecharts | 2022年世界500强数据分析可视化
  7. CSS控制鼠标光标样式
  8. ESP8266-Arduino编程实例-APDS-9930环境光和趋近感器驱动
  9. canva绘制满屏繁星 + 背景音乐 + css3炫酷3D照片集
  10. python-对水平和垂直投影图做曲线拟合