




已阅读5页,还剩15页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
c+内存池设计在项目中进程要对变量和对象分配空间,由于频繁的使用new和delete很消耗程序的运行时间,而且容易产生各种内存泄露,内存释放错误等问题。为此,需要设计一个通用的内存池来完成相关的分配和释放的工作。建立内存池:首先向系统申请一块内存,这块内存的大小由使用者根据需要设置初始内存大小。 定义一个如下面代码所示的双向链表,将从系统分配的内存分为若干块。使用双向链表方便指针向前和向后遍历查找。链表中*data指向了系统分配的内存,puser使用二级指针保存了内存申请者的地址,方便以后系统内存块更改,改变申请者的指向。后面会详细介绍。将双向链表指向指向内存如下所示:假设内存池初始块数为4块,每块的大小为100个字节,则向系统申请400个字节的内存块,每块的大小为100字节。之后使用双向链表data指针指向内存块,每个指针能分配的大小如图所示从大到小递减。对象内存分配:对内存的链表指针分配好后,用户可以使用内存池进行内存分配,对于用户的内存分配有两种情况,一种是在现有的内存池中能找到合适的内存块,另一种情况是现有内的内存池没有足够的内存块来分配,需要重新向系统申请内存来满足用户的需求。下面分别就这两种内存分配情况进行说明:情况1内存池有足够的内存块进行分配 假设用户申请了240个字节的内存空间,内存池现在有四个内存块空闲,每个内存块的大小为100字节,那么内存池将会给用户取整分配三个内存块。如上图所示,并将指向400内存块的指针的date返回给用户使用。情况2内存池没有足够的内存块进行分配接着上图,假设用户现在要接着分别300字节的内存空间,现有内存池的大小已经不能满足,因此需要扩大现有的内存池使用大小。考虑到由于分配给用户的内存空间必须要是连续的内存块,因此这个连续的内存块越大,能分配给用户的内存就多。因此使用c语言的realloc函数来满足要求。函数简介原型:extern void *realloc(void *mem_address, unsigned int newsize);语法:指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)。/新的大小一定要大于原来的大小,不然的话会导致数据丢失!头文件:#include 有些编译器需要#include ,在tc2.0中可以使用alloc.h头文件功能:先判断当前的指针是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回,如果空间不够,先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域(注意:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。返回值:如果重新分配成功则返回指向被分配内存的指针,否则返回空指针null。由realloc函数定义可知,新分配的内存空间可能是在原有的内存基础上扩充,还有可能是在另外的一个地方新开辟一块内存。无论哪种情况多要对新加的内存进行指针指向分配。并且对于第二种情况,会出现的问题是原有的指针全都失效。因为原有指向的内存已经不存在了,因此指向它的指针将失效,原有分配的对象也将失效。为了解决这个问题,在新分配内存后需要重定向原有的指针,并且使用二级指针改变已经分配了对象的地址的指向,使它指向新内存。重定向原有内存的指针的指向,和已经分配了内存的对象的指向。对象释放内存:假如先前的申请了250个字节分配了三个内存块的用户释放了内存,这时链表指针向后查找直到找到第一个被使用的内存块,或链表结尾。之后在先前查找直到找到前面第一个被使用的内存块或者是头指针,之后更新这个区间段内存块的大小。释放内存池:首先释放向系统申请的内存块,之后在清空所有的双向链表。释放向系统申请的内存释放双向链表。后续改进:1, 需要对多线程的支持,目前的内存池还只能在单线程的环境下运行。2, 如果之前得到内存的对象,在新内存分配前有指针复制操作,原有对象可以通过保存的指针地址进行重定向,但是之前分别的对象不能保证。引进对于分配的对象尽量不要使用指针复制。如果一定需要这么做,那就在每次使用前,在重定向一下。重新进行一次复制操作(保险起见,不知道我的表述是否清楚明白)。源代码:头文件链表节点的定义#include#include#include#include using namespace std;namespace memepooltypedef unsigned char eigthbyte;/内存池的默认大小和分配节点的默认大小static const size_t defaultmemepoolsize = 1000;static const size_t defaultmemenodesize = 100;/内存初始分配内容 二进制位1111 1111static const int new_allocated_memory_content = 0xff;/内存分配节点(双向链表)typedef struct tmemenode/指向前一节点tmemenode *first;/指向后一节点tmemenode *next;/节点大小size_t idatasize;/节点是否被使用bool isused;/分配的节点的后一节点tmemenode *pendnode;/记录内存池分配的首地址bool ismemebegin;/保存分配的内存地址eigthbyte *data ;/使用者对象的地址void *puser; tmemelinknode;内存池实现:namespace memepool/内存池的实现 作者邮箱class cmemepoolpublic:/线程池构造函数cmemepool(const size_t &sinitialmemorypoolsize = defaultmemepoolsize,const size_t &smemorychunksize = defaultmemenodesize);cmemepool();/分配内存void *getmemeroy(void *p,const size_t &ssize);/释放分配内存void freeallocmemeroy(void *p,const size_t &ssize);/释放内存池所有内存void freeallmemeroy();/展示内存池的使用情况void showthememepoolstatue();/获取错误信息void geterrorinfo();private: /禁止复制与构造,要传递就用引用吧 cmemepool(cmemepool *tcmemepool); cmemepool& operator =(cmemepool &tcmemepool); void allocpoolmemeroy(); void callinknodenum(); void calmemesize(); void linkmemerytonode(eigthbyte *palloc); void updatelinknodesize(tmemenode *pnode); void calneetlinknumber(const size_t &ssize); void* findmemenode(const size_t &ssize); tmemenode * searchallocnode(void *p); void cleanallmemedate(); void cleatalllinknode();void resetlinktomemery(); /双向链表的头节点 tmemelinknode *m_head; /双向链表的当前节点 tmemelinknode *m_current; /双向链表的最后节点 tmemelinknode *m_lastnode; eigthbyte *m_palloc; /保存第一次运行头地址 bool m_isfirst; /内存块分配数目 size_t m_number;/内存块总的数目 size_t m_allnumber; /每一个内存块的大小 size_t m_memlinksize; /内存池分配的大小 size_t m_memepollsize; /内存块总分配大小 size_t m_allaloctsize; /内存池使用的大小 size_t m_memepoolusesize; /内存池空闲的大小 size_t m_memepoolfreesize; /分配了多少个对象 size_t m_iuseobject; /保存错误信息 string m_serror; /保存请求分配内存用户信息 void *m_user;/-/recalloc分配新内存后,之前指向旧内存的指针就失效了/需要重新定位,之前分配对象的指向也要重新定位namespace memepool/* 内存池构造函数 by 风清扬song 13-07-28*/cmemepool:cmemepool(const size_t &sinitialmemorypoolsize,const size_t &smemorychunksize)/初始化内存池的大小m_memepollsize = sinitialmemorypoolsize;/初始化每个内存块的大小m_memlinksize = smemorychunksize;/初始化一些参数m_memepoolfreesize = 0;m_memepoolusesize = 0;m_current = null;m_lastnode = null;m_number = 0;m_allaloctsize = 0;m_allnumber = 0;m_iuseobject = 0;m_head = new tmemelinknode;m_head-next = null;m_head-first = null;m_head-data = null;m_isfirst = true;/分配线程池函数allocpoolmemeroy();/* 内存池析构函数 by 风清扬song 13-07-28*/cmemepool:cmemepool() freeallmemeroy();/* 内存池分配内存函数 by 风清扬song 13-07-28*/void cmemepool:allocpoolmemeroy()/计算需要的链表节点数目callinknodenum();/计算真正要分配的内存大小calmemesize();m_allnumber = m_allnumber + m_number;m_allaloctsize += m_memepollsize;m_memepoolfreesize += m_memepollsize;/追加分配内存,原有内存的内容不会受到影响m_palloc = (eigthbyte *)realloc(m_palloc,(m_allaloctsize)*sizeof(eigthbyte);/内存分配失败if(null = m_palloc)m_serror = alloc memeroy pool failture;return;/不是第一次分配内存if(false = m_isfirst) /新分配内存后原有指针全失效,需要重定向resetlinktomemery();/分配的内存内容初始化/ memset(void *) palloc), new_allocated_memory_content, m_memepollsize) ;/将分配的线程池内存与链表节点关联linkmemerytonode(&m_pallocm_allaloctsize - m_memepollsize);/* 将原内存的指针进行重定向(alloc后原有内存可能被释放了) by 风清扬song 13-07-28*/ void cmemepool:resetlinktomemery() tmemelinknode *ptemp = m_head-next;int iindex = 0;while(null != ptemp) /重定向指针链表的指向 ptemp-data = &m_pallociindex * m_memlinksize; if(null != ptemp-puser) /重定向用户指针的指向 *ptemp-puser = ptemp-data; iindex+; ptemp = ptemp-next; /* 计算需要的内存链表节点数目 by 风清扬song 13-07-28*/void cmemepool:callinknodenum()float ftempvalue = m_memepollsize / m_memlinksize; /向上取整需要的节点数目m_number = ceil(ftempvalue);/* 计算内存池真正分配的内存的大小 by 风清扬song 13-07-28*/void cmemepool:calmemesize()m_memepollsize = (size_t)(m_number * m_memlinksize);/* 将分配的内存和链表节点相关联 by 风清扬song 13-07-28*/void cmemepool:linkmemerytonode(eigthbyte *palloc) tmemelinknode *pnode; /遍历每一个节点分配空间 for(size_t iindex = 0; iindex next = m_head-next; m_head-next = pnode; pnode-first = m_head; m_lastnode = pnode; else pnode-next = m_lastnode-next; m_lastnode-next = pnode; pnode-first = m_lastnode; m_lastnode = pnode; m_lastnode-isused = false; m_lastnode-idatasize = m_memepollsize - iindex * m_memlinksize; m_lastnode-data = &pallociindex * m_memlinksize; m_lastnode-ismemebegin = false; m_lastnode-puser = null; /记录内存块的首地址,释放时使用 if(true = m_isfirst & 0 = iindex) m_lastnode-ismemebegin = true; m_isfirst = false; updatelinknodesize(m_lastnode);/* 更新当前节点的前后大小值 by 风清扬song 13-07-28*/void cmemepool:updatelinknodesize(tmemenode *pnode)tmemenode *ptemp;ptemp = pnode-next;int idatesize = 0;/当前节点的后一个节点没分配,得到它的datasize值if(null != ptemp & false = ptemp-isused) idatesize = ptemp-idatasize; /由最后一个节点在向前遍历,更新所有的节点大小值 int iindex = 1;while(pnode != m_head & false = pnode-isused)pnode-idatasize = iindex * m_memlinksize + idatesize;iindex+;pnode = pnode-first;m_current = pnode-next;/* 分配内存空间 by 风清扬song 13-07-28*/void *cmemepool:getmemeroy(void *p,const size_t &ssize) m_memepoolfreesize -= ssize; m_memepoolusesize += ssize; /保存请求内存分配的用户信息 m_user = p;/增加分配对象数目 m_iuseobject+;/有合适的内存块void *pfind = findmemenode(ssize);if(null != pfind)return pfind;tmemenode *ptemp;ptemp = m_current;m_current = m_current-next;/遍历内存块找到合适的内存while(ptemp != m_current) /走到结尾,从头来if(null = m_current) m_current = m_head-next;/跳过已经分配的节点if(true = m_current-isused)m_current = m_current-pendnode;/m_current = m_current-first;pfind = findmemenode(ssize);if(null != pfind)return pfind;if(ptemp = m_current)break;m_current = m_current-next;/在当前的所有节点链表中没有合适的,新分配吧m_memepollsize = ssize;allocpoolmemeroy();return findmemenode(ssize);/* 计算所需的内存块数目 by 风清扬song 13-07-28*/void cmemepool:calneetlinknumber(const size_t &ssize)float ftempvalue = ssize / m_memlinksize; /向上取整需要的节点数目m_number = ceil(ftempvalue);if(0 = m_number)m_number = 1;/* 找到合适的内存分配节点了 by 风清扬song 13-07-28*/void* cmemepool:findmemenode(const size_t &ssize)if(m_current-idatasize = ssize & false = m_current-isused)calneetlinknumber(ssize);size_t iindex = 0;tmemelinknode *ptemp = m_current;while(iindex isused = true; m_current = m_current-next; iindex+;/保存分配内存的用户信息ptemp-puser = m_user;/记录分配了几块内存,避免后续遍历ptemp-pendnode = m_current-next;return ptemp-data;elsereturn null;/* 收回分配的内存块 by 风清扬song 13-07-28*/void cmemepool:freeallocmemeroy(void *p,const size_t &ssize) /减少分配数目 m_iuseobject-; m_memepoolusesize -= ssize; m_memepoolfreesize += ssize; tmemenode *pfind = searchallocnode(p); if(null = pfind) m_serror = can not find the alloc point,you may use wrong; /恢复内存为初始化/memset(void *) pfind-data), new_allocated_memory_content, ssize) ; /计算向后移动多少内存块 calneetlinknumber(ssize); size_t iindex = 0; while(iindex != m_number) pfind-isused = false; pfind = pfind-next; iindex+; /内存归还后,更新前后节点的大小 updatelinknodesize(pfind-first);/* 查找之前分配内存的节点 by 风清扬song 13-07-28*/tmemenode * cmemepool:searchallocnode(void *p) tmemenode *ptemp = m_head-next; while(null != ptemp) if(ptemp-data = (eigthbyte *) p)/释放内存的用户清空之前保存的用户信息ptemp-puser = null;return ptemp;ptemp = ptemp-next; return null;/* 清空线程池 by 风清扬song 13-07-28*/void cmemepool:freeallmemeroy()/所有内存对象都释放了if(0 != m_iuseobject)m_serror = warning there is some object not release;cleanallmemedate();cleatalllinknode();/* 清空向系统申请的内存 by 风清扬song 13-07-28*/void cmemepool:cleanallmemedate() tmemelinknode *ptemp = m_head-next; while(null != ptemp) /内存被连城了一块,从首地址就可以全部删除if(ptemp-ismemebegin&null != ptemp-data)delete ptemp-data;return;ptemp = ptemp-next; /* 清空双向链表 by 风清扬song 13-07-28*/void cmemepool:cleatalllinknode() tmemelinknode *ptemp = m_head-next; while(null != ptemp) tmemelinknode *qtemp = ptemp; ptemp = ptemp-next; delete qtemp; if(null != m_head) delete m_head; /* 显示内存池运行状态 by 风清扬song 13-07-28*/void cmemepool:showthememepoolstatue() coutnnttt内存池使用状况输出tttnn; couttt总内存池大小:m_allaloctsize使用大小:m_memepoolusesize空闲大小:m_memepoolfreesizenext; int iindex
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年事业单位工勤技能-河北-河北土建施工人员五级(初级工)历年参考题库含答案解析(5套)
- 2025年事业单位工勤技能-河北-河北下水道养护工五级(初级工)历年参考题库含答案解析(5套)
- 2025年事业单位工勤技能-江苏-江苏放射技术员三级(高级工)历年参考题库含答案解析
- 2025年事业单位工勤技能-广西-广西汽车驾驶与维修员二级(技师)历年参考题库典型考点含答案解析
- 2025年事业单位工勤技能-广西-广西无损探伤工二级(技师)历年参考题库典型考点含答案解析
- 2025年事业单位工勤技能-广西-广西公路养护工二级(技师)历年参考题库含答案解析
- 2025年事业单位工勤技能-广东-广东食品检验工二级(技师)历年参考题库含答案解析
- 2025年事业单位工勤技能-广东-广东热处理工四级(中级工)历年参考题库含答案解析
- 2025年事业单位工勤技能-广东-广东垃圾清扫与处理工四级(中级工)历年参考题库典型考点含答案解析
- 2025年事业单位工勤技能-广东-广东信号工-机车信号设备维修三级(高级工)历年参考题库含答案解析
- 公共图书馆管理服务合同
- 【初三】【九年级】【物理】2025【秋】开学第一课主题班会(课件)
- 电商退换货流程标准操作手册
- 2025年法检系统书记员招聘考试(申论)历年参考题库含答案详解(5套)
- 2025年幼儿园教师《指南》《幼儿教师专业标准》学习测试题(附答案)
- (2025年标准)夜市经营协议书
- 加油站雷电安全知识培训课件
- 办公自动化使用教材课件
- 2025年佛山转业士官考试题库
- 2025年专业士官考试题库
- 院前急救技能大赛
评论
0/150
提交评论