收藏 分销(赏)

c--内存池设计-学位论文.doc

上传人:w****g 文档编号:2180777 上传时间:2024-05-22 格式:DOC 页数:20 大小:550KB
下载 相关 举报
c--内存池设计-学位论文.doc_第1页
第1页 / 共20页
c--内存池设计-学位论文.doc_第2页
第2页 / 共20页
c--内存池设计-学位论文.doc_第3页
第3页 / 共20页
c--内存池设计-学位论文.doc_第4页
第4页 / 共20页
c--内存池设计-学位论文.doc_第5页
第5页 / 共20页
点击查看更多>>
资源描述

1、C+内存池设计在项目中进程要对变量和对象分配空间,由于频繁的使用new和delete很消耗程序的运行时间,而且容易产生各种内存泄露,内存释放错误等问题。为此,需要设计一个通用的内存池来完成相关的分配和释放的工作。建立内存池:首先向系统申请一块内存,这块内存的大小由使用者根据需要设置初始内存大小。 定义一个如下面代码所示的双向链表,将从系统分配的内存分为若干块。使用双向链表方便指针向前和向后遍历查找。链表中*Data指向了系统分配的内存,pUser使用二级指针保存了内存申请者的地址,方便以后系统内存块更改,改变申请者的指向。后面会详细介绍。将双向链表指向指向内存如下所示:假设内存池初始块数为4块

2、,每块的大小为100个字节,则向系统申请400个字节的内存块,每块的大小为100字节。之后使用双向链表DATA指针指向内存块,每个指针能分配的大小如图所示从大到小递减。对象内存分配:对内存的链表指针分配好后,用户可以使用内存池进行内存分配,对于用户的内存分配有两种情况,一种是在现有的内存池中能找到合适的内存块,另一种情况是现有内的内存池没有足够的内存块来分配,需要重新向系统申请内存来满足用户的需求。下面分别就这两种内存分配情况进行说明:情况1内存池有足够的内存块进行分配 假设用户申请了240个字节的内存空间,内存池现在有四个内存块空闲,每个内存块的大小为100字节,那么内存池将会给用户取整分配

3、三个内存块。如上图所示,并将指向400内存块的指针的DATE返回给用户使用。情况2内存池没有足够的内存块进行分配接着上图,假设用户现在要接着分别300字节的内存空间,现有内存池的大小已经不能满足,因此需要扩大现有的内存池使用大小。考虑到由于分配给用户的内存空间必须要是连续的内存块,因此这个连续的内存块越大,能分配给用户的内存就多。因此使用C语言的realloc函数来满足要求。函数简介原型:extern void *realloc(void *mem_address, unsigned int newsize);语法:指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)。/新

4、的大小一定要大于原来的大小,不然的话会导致数据丢失!头文件:#include 有些编译器需要#include ,在TC2.0中可以使用alloc.h头文件功能:先判断当前的指针是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回,如果空间不够,先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域(注意:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。返回值:如果重新分配成功则返回指向被分配内存的指针,否则返回空指针NU

5、LL。由realloc函数定义可知,新分配的内存空间可能是在原有的内存基础上扩充,还有可能是在另外的一个地方新开辟一块内存。无论哪种情况多要对新加的内存进行指针指向分配。并且对于第二种情况,会出现的问题是原有的指针全都失效。因为原有指向的内存已经不存在了,因此指向它的指针将失效,原有分配的对象也将失效。为了解决这个问题,在新分配内存后需要重定向原有的指针,并且使用二级指针改变已经分配了对象的地址的指向,使它指向新内存。重定向原有内存的指针的指向,和已经分配了内存的对象的指向。对象释放内存:假如先前的申请了250个字节分配了三个内存块的用户释放了内存,这时链表指针向后查找直到找到第一个被使用的内

6、存块,或链表结尾。之后在先前查找直到找到前面第一个被使用的内存块或者是头指针,之后更新这个区间段内存块的大小。释放内存池:首先释放向系统申请的内存块,之后在清空所有的双向链表。释放向系统申请的内存释放双向链表。后续改进:1, 需要对多线程的支持,目前的内存池还只能在单线程的环境下运行。2, 如果之前得到内存的对象,在新内存分配前有指针复制操作,原有对象可以通过保存的指针地址进行重定向,但是之前分别的对象不能保证。引进对于分配的对象尽量不要使用指针复制。如果一定需要这么做,那就在每次使用前,在重定向一下。重新进行一次复制操作(保险起见,不知道我的表述是否清楚明白)。源代码:头文件链表节点的定义#

7、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;/内存分配节点(双向

8、链表)typedef struct TMemeNode/指向前一节点TMemeNode *first;/指向后一节点TMemeNode *next;/节点大小size_t idataSize;/节点是否被使用bool isUsed;/分配的节点的后一节点TMemeNode *pEndNode;/记录内存池分配的首地址bool isMemeBegin;/保存分配的内存地址EigthByte *Data ;/使用者对象的地址void *pUser; TMemeLinkNode;内存池实现:namespace MemePool/内存池的实现 作者邮箱a584851044class CMemePool

9、public:/线程池构造函数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();/展示内存池的使用

10、情况void ShowTheMemePoolStatue();/获取错误信息void GetErrorInfo();private: /禁止复制与构造,要传递就用引用吧 CMemePool(CMemePool *tCMemePool); CMemePool& operator =(CMemePool &tCMemePool); void AllocPoolMemeroy(); void CalLinkNodeNum(); void CalMemeSize(); void LinkMemeryToNode(EigthByte *PAlloc); void UpdateLinkNodeSize(T

11、MemeNode *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; /双向链表的最后节点 TM

12、emeLinkNode *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;

13、/分配了多少个对象 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

14、 = 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-Dat

15、a = 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 +

16、= 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();/分配的内

17、存内容初始化/ 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;whil

18、e(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

19、_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; iInde

20、x 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 =

21、&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

22、 *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;iI

23、ndex+;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 != pFin

24、d)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(NU

25、LL != 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;

26、/向上取整需要的节点数目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(iInde

27、x 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_MemePoolUseS

28、ize -= 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(i

29、Index != 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)/释放内存的用户清空之前保

30、存的用户信息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 CMemePo

31、ol: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 !=

32、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; whi

33、le(NULL != pTemp) coutn内存池号:iIndextt大小:idataSizett是否被使用:isUsednext; ;测试代码:int main(int argc, char* argv) CMemePool *g_ptrMemPool = new CMemePool() ; char *ptrCharArray = (char *) g_ptrMemPool-GetMemeroy(void*)&ptrCharArray,700) ;g_ptrMemPool-ShowTheMemePoolStatue(); char * ptrCharArrayB = (char *) g

34、_ptrMemPool-GetMemeroy(void*)&ptrCharArrayB,80) ;g_ptrMemPool-ShowTheMemePoolStatue(); char * ptrCharArrayC = (char *) g_ptrMemPool-GetMemeroy(void*)&ptrCharArrayC,400) ;g_ptrMemPool-ShowTheMemePoolStatue(); g_ptrMemPool-FreeAllocMemeroy(ptrCharArray, 700) ;g_ptrMemPool-ShowTheMemePoolStatue(); g_pt

35、rMemPool-FreeAllocMemeroy(ptrCharArrayC, 400) ;g_ptrMemPool-FreeAllocMemeroy(ptrCharArrayB, 80) ;ptrCharArray = (char *) g_ptrMemPool-GetMemeroy(void*)&ptrCharArray,1300) ;g_ptrMemPool-ShowTheMemePoolStatue();for(int i=0; iShowTheMemePoolStatue(); char c = ptrCharArray800; g_ptrMemPool-FreeAllocMemeroy(ptrCharArray, 1300) ; g_ptrMemPool-ShowTheMemePoolStatue();delete g_ptrMemPool ; std:cout MemoryPool Program finished. std:endl ;system(PA

展开阅读全文
相似文档                                   自信AI助手自信AI助手
猜你喜欢                                   自信AI导航自信AI导航
搜索标签

当前位置:首页 > 学术论文 > 其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        获赠5币

©2010-2024 宁波自信网络信息技术有限公司  版权所有

客服电话:4008-655-100  投诉/维权电话:4009-655-100

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :gzh.png    weibo.png    LOFTER.png 

客服