返回首页


目录
在C / C + +内存分配(通过malloc或new)可以采取了很多时间。
为了使事情变得更糟,内存会随着时间的推移片段,所以应用程序的性能会降低运行时,在一个长期的时间和/或执行了大量的内存(DE)的拨款。特别是如果你往往极少量的内存分配,堆变得支离破碎。 解决办法:您自己的内存池
一个(可能)解决方案可以是一个内存池。
一个"内存池"分配的内存在启动时的大量,将分成较小的块块。每次你从池中请求内存,它是采取从先前分配的块,而不是从操作系统。最大的优点是:很少(为none)堆的碎片速度比"正常"的内存(DE)的分配(例如,通过malloc,新等)
此外,你得到这些好处:检查内存池里面是一个任意指针写入您的硬盘"堆转储"(伟大的验尸调试等)一些"内存泄漏检测":当你还没有释放所有以前分配的内存,内存池将抛出一个断言
让我们看看在内存池UML架构:内存池的UML架构
该模式显示只有一小部分CMemoryPool类,使用Doxygen生成的文档进行了详细的类描述的看看。
所以,它的实际工作呢?一个字左右的MemoryChunks
正如你可以看到从UML模式,内存池下辖SMemoryChunk结构(m_ptrFirstChunk,m_ptrLastChunk,并m_ptrCursorChunk)的指针。这些块建立的内存块链表。每个点列表中的下一个块。从操作系统分配一个内存块时,它会完全由SMemoryChunks管理。让我们仔细看看在这样一大块:typedef结构SMemoryChunk{ TB的数据; / /实际的数据 标准:为size_t的数据大小; / /大小quot; Dataquot;座 STD:为size_t UsedSize; / /实际使用的尺寸 BOOL IsAllocationChunk; / / TRUE时,这个MemoryChunks   ; / /指向一个quot; Dataquot;座 & #160; 可以释放/ /通过"自由()quot; SMemoryChunk下一步; / /指向下一个MemoryChunk   ; / /在列表(可能为NULL)} SMemoryChunk;
每块持有指向:小块的内存(数据),从该块(数据大小)开始,内存的总大小实际使用的大小(UsedSize)和一个指针列表中的下一个块(下一步)。第一步:预分配的内存
当您呼叫CMemoryPool的构造函数时,内存池从操作系统分配其第一个(大)内存块./******************构造******************/CMemoryPool:CMemoryPool(CONST STD:为size_t放大器; sInitialMemoryPoolSize 常量的std::为size_t放大器; sMemoryChunkSize  0; 常量的std::为size_t放大器; sMinimalMemorySizeToAllocate &# 160; BOOL bSetMemoryData){ m_ptrFirstChunk = NULL; m_ptrLastChunk = NULL; m_ptrCursorChunk = NULL; m_sTotalMemoryPoolSize = 0; m_sUsedMemoryPoolSize = 0; m_sFreeMemoryPoolSize = 0; m_sMemoryChunkSize = sMemoryChunkSize; & #160;m_uiMemoryChunkCount = 0; m_uiObjectCount = 0; m_bSetMemoryData = bSetMemoryData; m_sMinimalMemorySizeToAllocate = sMinimalMemorySizeToAllocate; / /分配的内存从操作系统的初始金额... AllocateMemory(sInitialMemoryPoolSize);}
通常初始化所有类成员是在这里完成,并AllocateMemory最终将要求从操作系统的内存./******************AllocateMemory******************/LT; CODEgt; BOOL CMemoryPool:AllocateMemory(CONST STD:为size_t放大器; sMemorySize){ STD:为size_t sBestMemBlockSize = CalculateBestMemoryBlockSize(sMemorySize); / /从操作系统分配 TB的* ptrNewMemBlock =(TB的*)malloc的(sBestMemBlockSize); ... ...
因此,如何内存池管理这方面的数据?第二步:分配的内存分割
如前所述,内存池管理SMemoryChunks所有数据。要求从操作系统的内存后,没有块和实际内存块之间的连接:在初次分配的内存池
我们需要SMemoryChunk结构数组分配管理,内存块:/ / AllocateMemory(续): ... ... 无符号整型uiNeededChunks = CalculateNeededChunks(sMemorySize); / /分配管理内存块阵列 SMemoryChunk * ptrNewChunks = (SMemoryChunk *)malloc的((uiNeededChunks * SIZEOF(SMemoryChunk))); ASSERT(((ptrNewMemBlock)放大器;放大器;(ptrNewChunks)) 放大器;放大器",错误:系统跑出来的Memoryquot;); ... ...
CalculateNeededChunks()将计算管理所需的内存一定量的块数。在分配的块(通过malloc),ptrNewChunks点SMemoryChunks阵列。注意,阵列中的块只持有垃圾数据,因为我们还没有分配任何有意义的数据块成员。内存池"堆"看起来像这样:SMemoryChunk分配后的内存池
尽管如此,有没有数据块和块之间的连接。但AllocateMemory()将照顾它。 LinkChunksToData()最终将内存块和块连结在一起。这也将有效的数据分配到每块会员...//( AllocateMemory()续): ... ... / /副分配的内存块链表的MemoryChunks 返回LinkChunksToData(ptrNewChunks,uiNeededChunks,ptrNewMemBlock);
让我们在LinkChunksToData细看():/******************LinkChunksToData******************/BOOL CMemoryPool:LinkChunksToData(SMemoryChunk * ptrNewChunks 无符号整型uiChunkCount,TB的* ptrNewMemBlock){ SMemoryChunk * ptrNewChunk = NULL; 无符号整型uiMemOffSet = 0; BOOL bAllocationChunkAssigned = FALSE; 为(无符号​​int I = 0;我LT; uiChunkCount;我) { 如果(!m_ptrFirstChunk) { & #160; m_ptrFirstChunk = SetChunkDefaults(AMP(ptrNewChunks [0])); m_ptrLastChunk = m_ptrFirstChunk;  ; m_ptrCursorChunk = m_ptrFirstChunk; } 60; 其他 { ptrNewChunk = SetChunkDefaults(AMP(ptrNewChunks [I])); m_ptrLastChunk - GT下一步= ptrNewChunk; m_ptrLastChunk = ptrNewChunk; } uiMemOffSet =(I *((无符号整数)m_sMemoryChunkSize)); m_ptrLastChunk - GT;数据=安培(ptrNewMemBlock [uiMemOffSet]);  0;/ /将分配到新的内存块的第一个块 / /一个quot; AllocationChunkquot;这意味着,这一大块存储 / /"originalquot;指针的MemBlock和负责 / / quot;()quot;的记忆.... 如果(!bAllocationChunkAssigned) { m_ptrLastChunk - GT; IsAllocationChunk = TRUE; bAllocationChunkAssigned =; } } 返回RecalcChunkMemorySize(m_ptrFirstChunk,m_uiMemoryChunkCount);}
让我们在这个重要的方法一步一步看:第一线检查,如果已经有块列表中:... 如果(!m_ptrFirstChunk) ... ...
一开始,这是情况并非如此。因此,我们首次分配我们的内部类成员:... m_ptrFirstChunk = SetChunkDefaults(AMP(ptrNewChunks [0])); m_ptrLastChunk = m_ptrFirstChunk; m_ptrCursorChunk = m_ptrFirstChunk; ... ...
m_ptrFirstChunk点,现在的第一块块阵列。每块管理完全m_sMemoryChunkSize字节的内存块。 "偏移"值将被计算,使每块将指向一个特定部分的内存块。 uiMemOffSet =(I *((无符号整数)m_sMemoryChunkSize)); m_ptrLastChunk - GT;数据=安培(ptrNewMemBlock [uiMemOffSet]);
此外,从数组中的每一个新SMemoryChunk将被添加到链表的最后一个元素(并最终成为最后一个元素本身):... ... m_ptrLastChunk - GT下一步= ptrNewChunk; m_ptrLastChunk = ptrNewChunk; ... ...
在随后的"循环"的通过,将陆续分配内存池的有效数据到阵列中的所有块。的内存和块连在一起的,指向有效的数据
最后,我们必须重新计算每个块可以管理的内存总量。这是相当费时,而且必须做的每一次新的内存从操作系统的内存池。每个块的内存总量,将被分配到的块数据大小成员./******************RecalcChunkMemorySize******************/BOOL CMemoryPool:RecalcChunkMemorySize(SMemoryChunk * ptrChunk  0; 无符号整型uiChunkCount){ 无符号整型uiMemOffSet = 0; 为(无符号​​int I = 0;我LT; uiChunkCount;我) { (ptrChunk) {  60; uiMemOffSet =(I *((无符号整数)m_sMemoryChunkSize)); ptrChunk - GT;数据大小= (((无符号整数)m_sTotalMemoryPoolSize) - uiMemOffSet); & #160; ptrChunk = ptrChunk - GT;下一步; }  60; 其他 { 断言(假放大器;放大器; quot;错误:ptrChunk == NULLquot;); 返回false; } } 返回true;}
后RecalcChunkMemorySize,每块都知道的可用记忆体,它是指向量。因此,它变得非常容易,以确定是否能够保持一个特定的内存量一大块,时的数据大小成员比请求的内存量(或等于)的UsedSize成员是0,那么该块有能力持有的内存。最后,内存分段完成。为了使事情少抽象,让我们假设,内存池包含600个字节,每块是100字节。{五}内存分段完成。每块管理正好是100字节第三步:要求从内存池的内存如果用户请求的内存池
那么,会发生什么?最初,在内存池中的所有数据是免费提供:{中六}所有可用的内存块
让我们看看在GetMemory :/******************GetMemory******************/无效* CMemoryPool:GetMemory(const的STD:为size_t放大器; sMemorySize){ STD:为size_t sBestMemBlockSize = CalculateBestMemoryBlockSize(sMemorySize); SMemoryChunk * ptrChunk = NULL; 而(!ptrChunk) { / /是一个大块可用于保存请求的内存量? ptrChunk = FindChunkSuitableToHoldMemory(sBestMemBlockSize); LT; CODEgt;(ptrChunk!) { / /没有块可以找到 / / = GT内存池是为小。我们已要求 & #160; / /从操作系统的内存....  60;sBestMemBlockSize = MaxValue的(sBestMemBlockSize CalculateBestMemoryBlockSize(m_sMinimalMemorySizeToAllocate)); AllocateMemory(sBestMemBlockSize);  ; } } / /最后一个合适的块被发现。 / /调整内部quot值; TotalSizequot; /"UsedSizequot;成员和 / / MemoryChunk本身的价值。 m_sUsedMemoryPoolSize = sBestMemBlockSize; m_sFreeMemoryPoolSize -= sBestMemBlockSize; m_uiObjectCount; SetMemoryChunkValues​​(ptrChunk,sBestMemBlockSize); / /最终用户返回指针 返回((无效*)ptrChunk - GT,数据);}
当用户请求从内存池的内存,它会搜索一大块是持有所要求的数额的能力清单。这意味着:该块数据大小必须大于或等于请求的内存量UsedSize块必须为0
这样做的FindChunkSuitableToHoldMemory方法。如果返回NULL,则没有内存可用内存池。这将导致一个Allo​​cateMemory呼叫(如上所述),这将要求更多的内存,从OS。如果返回值不为NULL,一个有效的块被发现。 SetMemoryChunkValues​​将调整块的内部值,而最终的数据指针返回给用户.../******************SetMemoryChunkValues******************/无效CMemoryPool:SetMemoryChunkValues​​(SMemoryChunk * ptrChunk 常量的std::为size_t放大器; sMemBlockSize)(ptrChunk) { ptrChunk - GT; UsedSize = sMemBlockSize; } ... ...}
让我们假设,即用户要求从我们的内存池250个字节:{七}使用中的存储
正如你可以看到,每个内存块管理250个字节100字节,所以只是不适合在那里。会发生什么?那么,GetMemory将返回从第一块数据指针和设置UsedSize成员300个字节,因为300个字节是最小的内存量可以通过块管理,是GT = 250个字节。 (300 - 250 = 50)字节左边是所谓的"内存开销"的内存池(除了块本身所需要的内存)。这是不是那么糟糕,因为它似乎的,因为内存仍可使用(它仍然是在内存池)。
当FindChunkSuitableToHoldMemory有效的块搜索,它会跳只有一个"空块"到另一个"空块"。这意味着,如果有人请求另一个内存块,第四块的例子(一个300字节)将成为下一个"有效"的块。跳转到下一个有效的块
使用的代码是简单而直接:只包含"CMemoryPool.h"在您的应用程序,所有相关文件,并添加到您的IDE / Makefile中:CMemoryPool.hCMemoryPool.cppIMemoryBlock.hSMemoryChunk.h
你刚才创建的CMemoryPool类的实例,你就可以开始从它分配内存。所有的内存池的配置是在CMemoryPool构造(可选参数)。有看看头文件("CMemoryPool.h")或使用Doxygen - doku。所有文件都严重(Doxygen的)记录。用法exampleMemPool:CMemoryPool * g_ptrMemPool =新的内存池:CMemoryPool();CHAR * ptrCharArray =(CHAR *)g_ptrMemPool - GT; GetMemory(100);... ...g_ptrMemPool - GT; FreeMemory(ptrCharArray 100);删除g_ptrMemPool;内存转储
你可以写在任何时间通过WriteMemoryDumpToFile(strFileName)的"内存转储"到您的硬盘。让我们来看看一个简单的测试类的构造器(重载new和delete运算符使用的内存池):/******************构造******************/MyTestClass::MyTestClass(){ m_cMyArray [0] ="H"; m_cMyArray [1] ='E'; &# 160;m_cMyArray [2] ='L'; m_cMyArray [3] ='L'; m_cMyArray [4] ='O'; m_cMyArray [5] = NULL; m_strMyString ="这是一个小的考验Stringquot; m_iMyInt = 12345; m_fFloatValue = 23456.7890f; m_fDoubleValue = 6789.012345; 下一步=;} MyTestClass * ptrTestClass =新MyTestClass;g_ptrMemPool - GT; WriteMemoryDumpToFile("; MemoryDump.binquot";);
在看内存转储文件("MemoryDump.bin"):

正如你可以看到,这些都是MyTestClass在内存转储类成员的所有值。显然,"Hello"的字符串("m_cMyArray")是有,所以也整数值m_iMyInt(3930 0000 = 0x3039 = 12345十进制)等。这是伟大的验尸调试... ...
我做了一些非常简单的速度测试在Windows(通过timeGetTime()),但结果应该显示的内存池,可以大大加快应用程序。所有测试已与微软Visual Studio NET 2003的调试版本(测试机:英特尔奔腾IV处理器(32位),1GB内存,微软Windows XP专业)。/ /阵列测试(内存池):为(无符号​​整数J = 0,J LT; TestCount,J){ / / ARRAYSIZE = 1000 CHAR * ptrArray =(CHAR *)g_ptrMemPool - GT; GetMemory(ARRAYSIZE); g_ptrMemPool - GT; FreeMemory(ptrArray,ARRAYSIZE);} / /阵列测试(堆):为(无符号​​整数J = 0,J LT; TestCount,J){ / / ARRAYSIZE = 1000 CHAR * ptrArray =(CHAR *)malloc的(ARRAYSIZE); 免费(ptrArray);}MemoryPool和堆"数组测试"(重载新建/删除)/ /类测试的结果为(无符号​​整数J = 0,J LT; TestCount,J){ MyTestClass * ptrTestClass =新MyTestClass; 删除ptrTestClass;}结果"类测试"(重载的new / delete操作符的)
代码已经过测试,在MS Windows和Linux下面的C编译器(S):微软Visual C + + 6.0微软的Visual C NET 2003的MinGW(GCC)3.4.4(Windows)中GCC 4.0.X(的Debian GNU Linux的)
项目文件为Microsoft Visual C + + 6.0(*. DSW,*. DSP)和微软的Visual C NET 2003(*. sln的,包含在下载的*. vcproj)。这个内存池只使用ANSI / ISO C,因此,它应该编译在任何一个像样的C编译器的操作系统。应该没有问题,它使用64位处理器。
注意:内存池不是线程安全的!
这个内存池是从完善;-)的TODO列表包括:对于巨额的内存,内存的"开销"可能相当大。一些CalculateNeededChunks调用可以扒掉重新设计一些方法= GT速度更高达。 ;-)更多的稳定性试验(尤其是对于很长的运行的应用程序)。线程安全的。2006年5月9日:首次发布。
EoF进行

回答

评论会员:zjusomwu 时间:2011/12/07
嗨,我有这个程序在Linux下测试,令人惊讶的结果:池版本比标准版要慢得多,其结果是:
AllocatingAllocating内存(对象尺寸:1000)...确定
内存池(类测试)的结果:271毫秒
分配内存(对象大小:1000)...确定
结果堆(类测试):138毫秒
分配内存(对象大小:10056)...确定
内存池(类测试)的结果:881毫秒
分配内存(对象大小:10056)...确定
结果堆(类测试):585毫秒

那么,有什么问题和如何解决它
评论会员:?tecnoc 时间:2011/12/07
?如果我想安装在C#我该怎么办感谢
评论会员:cool_sni 时间:2011/12/07
问题1:此代码假定从操作系统下的内存分配是会传染给前一个

替换此:

RecalcChunkMemorySize(m_ptrFirstChunk,m_uiMemoryChunkCount);有了这样的:
RecalcChunkMemorySize(ptrNewChunks,uiChunkCount)

重新计算一个先前分配的块数据大小是一个坏主意,因为当新的数据块是分配的,他们是抱着一个新的数据,你不能用旧块给予客户端所需的内存作为新分配的内存是不传染的前一个。{BR } 问题2:泄漏时,释放出
添加
无效CMemoryPool:DeallocateAllChunks()

(ptrChunkToDelete)
{
免费(((无效*)ptrChunkToDelete))
}

| vccodes
评论会员:我曾尝试代码 时间:2011/12/07
乔伍德伯里
评论会员:游客 时间:2011/12/07
无谓的文章写得非常糟糕的代码。此外,一旦你在释放模式测试,使用本地C堆代码
。罗宾
评论会员:游客 时间:2011/12/07
?这是C,不是C,那么,为什么你使用typedef结构,malloc和无效*{BR}我想你需要学习的模板,新/删除和RIIA。无需再做手动在C
。DeepZer0
评论会员:游客 时间:2011/12/07
调试建立的分析是不是真的准确,因为它增加了一个检查默认情况下,整个
。DanDanger2000
评论会员:游客 时间:2011/12/07
例如:codepreMemPool::CMemoryPool*ptrMemPool=spanclass="code-keyword"new/spanMemPool::CMemoryPool();spanclass="code-keyword"void/span*p1=ptrMemPool-spanclass="code-keyword">/spanGetMemory(spanclass="code-digit"700/span);spanclass="code-comment"///spanspanclass="code-comment"step1/spanspanclass="code-keyword"void/span*p2=ptrMemPool-spanclass="code-keyword">/spanGetMemory(spanclass="code-digit"300/span);spanclass="code-comment"///spanspanclass="code-comment"step2/span/pre/code第1步后,CMemoryPool对象已分配1024字节(假设第一个地址是0x00912a30)和P1指出0x00912a30。第2步后,CMemoryPool对象已分配另外1024个字节(假设第一个地址是0x00913108)和P2指出0x00912d30。但P2[0x00912d30,0x00912d30300]内存[0x00912a30,0x00912a301024]内存[0x00913108,0x009131081024]区顺便说一下,这个逻辑是不好的。在代码中,如果想找到一个合适大小的内存,它必须找到一个接一个。
shacgray
评论会员:游客 时间:2011/12/07
喜。我真的很新的内存管理,特别是在如何实现一个。多次,我一直在学习您的文章,我仍然无法找到如何关联的实例化的数据预分配内存?说,我有一个CObject类和实例化它通常://获取内存使用的内存池。...CObject的*ptrCObject=新CObject的();...//释放内存使用的内存池。如果我的假设是正确的,你上面的代码,只是从操作系统分配内存通过内存池mallocing。然后我们有另一个新CObject的(从操作系统分配内存)调用。能否请你引导我更理解这个概念呢?imgsrc=http://www.orcode.com/upimg/2011_12_07_01_00_07_12.gif=安德烈
mazenb
评论会员:游客 时间:2011/12/07
嗨,的内存池和"正常的"C-类之间的"联系"是通过重载"新"的运营商。在C语言中的"覆盖"默认的"新"运营商:因此,当执行//======={BR}CObject的*ptrCObject=新CObject的();//======={BR}从"新"MemoryPool获得方法的执行(而不是操作系统之一)。有一个在"main.cpp的"查找文件。*无效MyTestClass_OPOverload::新的运营商(STD:为size_tObjectSize)我希望回答您的问题。关于丹尼尔----------{BR}DanDanger
liangkz
评论会员:游客 时间:2011/12/07
主席先生,你的代码是惊人的,真正我是fresher.and我想知道什么是批处理文件"MakeDoxygenDoku.bat"使用?你能告诉我吗?用最好的问候!SHAC
liangkz
评论会员:游客 时间:2011/12/07
我有这个问题B类{INTID;双X,Y,}A类{性病::list的安全带;}当我做*ptrTestClass=(A*)g_ptrMemPool-GetMemory(ARRAYSIZE)安全带未初始化,然后使用安全带的命令创建在代码崩溃。任何想法如何,我可以初始化列表?MB
woolrara
评论会员:游客 时间:2011/12/07
如何调用GetMemory()和FreeMemory()的顺序,我得到了一个['断言失败:(m_uiObjectCount==0)放大器;放大器;"警告:内存泄漏:您还没有释放所有分配的内存,文件\CMemoryPool.cpp,第53行";NBSP什么更重要的,使用以下代码段:NBSP〔/*#定义计数100nbsp;//无论数量GT;0;#定义ADD_SIZE130nbsp;//或120元,稍大或更小的DEFAULT_MEMORY_CHUNK_SIZE*///TestClass1是一个类来保存一个内存块(I=0;我\LT"计数;我){识别TestClass[I]=(TestClass1*)g_ptrMemPool-GT;GetMemory(sizeof(TestClass1)的);如果((4)%5==0)-;//释放一些识别TestClass,然后从内存池NBSP分配内存的数量;{-;g_ptrMemPool-GTFreeMemory((无效)*识别TestClass[I],SIZEOF(TestClass1))字符*TEMP=(CHAR*g_ptrMemPool-GT);GetMemory(SIZEOF(TestClass1)ADD_SIZE)}}我追查allcator,并发现顺便说一句:你的程序已经在逻辑上完全错误的,我的英语不够好,给一个非常精确的表达,我发现。SCU_CN
Yusaku
评论会员:游客 时间:2011/12/07
这里是一个例子:假设你已拨出7的内存块,索引从0到6,1)。要求从2块内存池的内存,你得到0和1,2)。要求从2块内存池的内存,你有2和3,3)。要求从2块内存池的内存,你有4和5,4)*释放2了2块内存),这意味着释放块2和3,现在你有2,3,6都是空的。5)。要求从3块内存池的内存,在你的算法,我可能会得到2,3,4。在这里,4索引块,还没有被释放和再次分配,这是不好的。SCU_CN
DanDanger2000
评论会员:游客 时间:2011/12/07
imgsrc=http://www.orcode.com/upimg/2011_12_07_01_00_07_13.gif/******************{BR}DeallocateAllChunks******************/{BR}无效CMemoryPool:DeallocateAllChunks(){SMemoryChunk*ptrChunk=m_ptrFirstChunk;SMemoryChunk*ptrChunkToDelete=NULL;(ptrChunk){(ptrChunkIsAllocationChunk){(ptrChunkToDelete){免费(((无效*)ptrChunkToDelete))//woolrara插入 ptrChunkToDelete=NULL;//〜woolrara插入}ptrChunkToDelete=ptrChunk;}ptrChunk=ptrChunk-下一步;}//woolrara插入(ptr_ChunkToDelete){免费(((无效*)ptrChunkToDelete))}//〜woolrara插入}//最后ptr_ChunkToDelete是内存泄漏的情况下//创建-破坏^^;
Yusaku
评论会员:游客 时间:2011/12/07
嗨,我也是一个初学者,现在学习记忆管理imgsrc=http://www.orcode.com/upimg/2011_12_07_01_00_07_14.gif有在你的程序中的一些错误:1。问题:SkipChunks引起一些问题。一旦计划达到的内存池的结束,我们不能回去字符*pMem1=(CHAR*)g_ptrMemPool-GetMemory(512)字符*pMem2=(CHAR*)g_ptrMemPool-GetMemory(512)g_ptrMemPoolFreeMemory(pMem1512)CHAR*pMem3=(CHAR*)g_ptrMemPool-GetMemory(100);//不能获得内存解决方案:(函数SkipChunks)(无符号intI=0;我下一步;2。问题:在FreeChunks,忘了恢复m_sFreeMemoryPoolSize后内存中释放3。问题:当我们的最后一个块的可用内存,"ptrCurrentChunk=ptrCurrentChunk"下一步";"ptrCurrentChunk将设置为NULL(类似的问题问题1)建议:可能是最后一个块的next指针指向m_ptrFirstChunk?4。没有真正的好处:我们应该永远记住数组的大小,我们使用了-_-B5。bcoz将在同一个地方作为pMem2的分配问题:pMem3,第一块显示它的体积是1024,但实际上,从128到1024pMem2空间字符*pMem1=(CHAR*)g_ptrMemPool-GetMemory(100)字符*pMem2=(CHAR*)g_ptrMemPool-GetMemory(800)g_ptrMemPoolFreeMemory(pMem1100)字符*pMem3=(CHAR*)g_ptrMemPool-GetMemory(1000)
国乒太阳
评论会员:游客 时间:2011/12/07
错误报告imgsrc=http://www.orcode.com/upimg/2011_12_07_01_00_07_14.gif感谢我会尽量尽快解决这些问题.....顺便说一句:你能详细解释问题4和第5多一点点?----------{BR}DanDanger
DanDanger2000
评论会员:游客 时间:2011/12/07
哈哈,你回答快速!其实,四是不是一个错误,但作为一个用户,我所期望的不知道有多大的内存是空闲内存:g_ptrMemPoolFreeMemory(pMem1);问题5:pMem3内存将包括pMem2内存,让我们的变化STH,这将是明确的://改变一些定义,那么我们就可以很容易得到的问题DEFAULT_MEMORY_POOL_SIZE=24;DEFAULT_MEMORY_CHUNK_SIZE=8; //测试代码的主要功能字符*pMem1=(CHAR*)g_ptrMemPool-GetMemory(8)字符*pMem2=(CHAR*)g_ptrMemPool-GetMemory(16)(I=0;iFreeMemory(pMem12);字符*pMem3=(CHAR*)g_ptrMemPool-GetMemory(24)(I=023,我)pMem3[I]='A';pMem3[我]=0;你会发现,pMem2改变后,我们设置pMem3。
会员751669
评论会员:游客 时间:2011/12/07
您好,你修复这些错误?G.P.
lij0526
评论会员:游客 时间:2011/12/07
您好,不幸的是,我没有真正时间现在的内存池错误修复(在我的大学有些沉重的考试都在等待...).{BR}只要我得到了一些更多的空余时间,我会尽量解决这些问题....{BR}----------{BR}DanDanger
rm822
评论会员:游客 时间:2011/12/07
嗨,我有解决这些问题,主要代码如下:SMemoryChunk*CMemoryPool:FindChunkSuitableToHoldMemory(CONSTSTD:为size_t放大器;sMemorySize)(ptrChunk-GT,数据大小GT=sMemorySize){如果(ptrChunk-GT;UsedSize==0){//开始jiang.j.q2011年7月12日(ptrChunk-GT;数据==m_ptrFirstChunk-GT;数据){如果(m_sMemoryChunkSizeGT=sMemorySize){m_ptrCursorChunk=ptrChunk;返回ptrChunk;}ELSE{无符号整型nCanUse=m_sMemoryChunkSize;SMemoryChunk*ptrChunk2=ptrChunk;(ptrChunk2-GT;下一页){=ptrChunk2ptrChunk2-GT;下一步;如果(ptrChunk2-GT;UsedSize==0){nCanUse=m_sMemoryChunkSize;如果(nCanUseGT=sMemorySize)打破;}ELSE{打破;}}如果(nCanUseGT=sMemorySize){m_ptrCursorChunk=ptrChunk;返回ptrChunk;}}}//结束jiang.j.q{m_ptrCursorChunk=ptrChunk;返回ptrChunk;}}}
DanDanger2000
评论会员:游客 时间:2011/12/07
第四届问题,虽然FreeMemory函数作为第二个参数的数组的大小,在它的函数体,参数不被用于尚未
。jadderbao
评论会员:游客 时间:2011/12/07
你dualcore英特尔CPUWin2003服务器programm(原EXE瓦特\O重新编译)MemoryPool计​​划开始......创建MemoryPool....OK分配内存(对象大小:1000)...确定内存池(阵列测试)的结果:62毫秒分配内存(对象大小:1000)...确定堆(阵列测试)结果:49毫秒分配内存(对象大小:10088)...确定内存池(类测试)结果:327毫秒分配内存(对象大小:10088)...确定结果堆(类测试):393毫秒删除内存池....确定MemoryPool计​​划完成...按任意键继续。。MSVC的堆和Windows堆多CPU系统和concurent访问进行了优化,你可以看到一个简单的测试并不意味着什么。