当前位置导航:炫浪网>>网络学院>>编程开发>>C++教程>>C++进阶与实例

C/C++的内存分配的解决方案

    C/C++的内存分配(通过malloc或new)可能需要花费很多时。

    更糟糕的是,随着时间的流逝,内存(memory)将形成碎片,所以一个应用程序的运行会越来越慢当它运行了很长时间和/或执行了很多的内存分配(释放)操作的时候。特别是,你经常申请很小的一块内存,堆(heap)会变成碎片的。

    解决方案:你自己的内存池一个(可能的)解决方法是内存池(Memory Pool)。

    在启动的时候,一个“内存池”(Memory Pool)分配一块很大的内存,并将会将这个大块(block)分成较小的块(smaller chunks)。每次你从内存池申请内存空间时,它会从先前已经分配的块(chunks)中得到,而不是从操作系统。最大的优势在于:

    1:非常少(几没有) 堆碎片

    2: 比通常的内存申请/释放(比如通过malloc, new等)的方式快另外,你可以得到以下好处:1:检查任何一个指针是否在内存池里2:写一个“堆转储(Heap-Dump)”到你的硬盘(对事后的调试非常有用)

    3: 某种“内存泄漏检测(memory-leak detection)”:当你没有释放所有以前分配的内存时,内存池(Memory Pool)会抛出一个断言(assertion)。

    SMemoryChunk.h

#ifndef __SMEMORYCHUNK_H__
#define __SMEMORYCHUNK_H__

typedef unsigned char TByte ;

struct SMemoryChunk
{
  TByte *Data;                //数据 
  std::size_t DataSize;        //该内存块的总大小
  std::size_t UsedSize;        //实际使用的大小
  bool IsAllocationChunk;    
  SMemoryChunk *Next;        //指向链表中下一个块的指针。
};

#endif

    IMemoryBlock.h

#ifndef __IMEMORYBLOCK_H__
#define __IMEMORYBLOCK_H__

class IMemoryBlock
{
  public :
    virtual ~IMemoryBlock() {};

    virtual void *GetMemory(const std::size_t &sMemorySize) = 0;
    virtual void FreeMemory(void *ptrMemoryBlock, const std::size_t &sMemoryBlockSize) = 0; 

};

#endif

    CMemoryPool.h

#ifndef __CMEMORYPOOL_H__
#define __CMEMORYPOOL_H__


#include "IMemoryBlock.h"
#include "SMemoryChunk.h"


static const std::size_t DEFAULT_MEMORY_POOL_SIZE        = 1000;//初始内存池的大小
static const std::size_t DEFAULT_MEMORY_CHUNK_SIZE       = 128;//Chunk的大小
static const std::size_t DEFAULT_MEMORY_SIZE_TO_ALLOCATE = DEFAULT_MEMORY_CHUNK_SIZE * 2;

class CMemoryPool : public IMemoryBlock
{
public:
    CMemoryPool(const std::size_t &sInitialMemoryPoolSize = DEFAULT_MEMORY_POOL_SIZE, 
                const std::size_t &sMemoryChunkSize = DEFAULT_MEMORY_CHUNK_SIZE,
                const std::size_t &sMinimalMemorySizeToAllocate = DEFAULT_MEMORY_SIZE_TO_ALLOCATE,
                bool bSetMemoryData = false
                );


    virtual ~CMemoryPool();

    //从内存池中申请内存
    virtual void* GetMemory(const std::size_t &sMemorySize);
    virtual void  FreeMemory(void *ptrMemoryBlock, const std::size_t &sMemoryBlockSize);
    
private:
    //申请内存OS
    bool AllocateMemory(const std::size_t &sMemorySize);
    void FreeAllAllocatedMemory();
    
    //计算可以分多少块
    unsigned int CalculateNeededChunks(const std::size_t &sMemorySize);

    //计算内存池最合适的大小
    std::size_t CMemoryPool::CalculateBestMemoryBlockSize(const std::size_t &sRequestedMemoryBlockSize);
    
    //建立链表.每个结点Data指针指向内存池中的内存地址
    bool LinkChunksToData(SMemoryChunk* ptrNewChunks, unsigned int uiChunkCount, TByte* ptrNewMemBlock);
    
    //重新计算块(Chunk)的大小1024--896--768--640--512------------
    bool RecalcChunkMemorySize(SMemoryChunk* ptrChunk, unsigned int uiChunkCount);
    
    SMemoryChunk* SetChunkDefaults(SMemoryChunk *ptrChunk);
    

    //搜索链表找到一个能够持有被申请大小的内存块(Chunk).如果它返回NULL,那么在内存池中没有可用的内存
    SMemoryChunk* FindChunkSuitableToHoldMemory(const std::size_t &sMemorySize);

    std::size_t MaxValue(const std::size_t &sValueA, const std::size_t &sValueB) const;
    
    void SetMemoryChunkValues(SMemoryChunk *ptrChunk, const std::size_t &sMemBlockSize);

    SMemoryChunk* SkipChunks(SMemoryChunk *ptrStartChunk, unsigned int uiChunksToSkip);

private:

    SMemoryChunk *m_ptrFirstChunk;
    SMemoryChunk *m_ptrLastChunk;   
    SMemoryChunk *m_ptrCursorChunk;

    std::size_t m_sTotalMemoryPoolSize;  //内存池的总大小
    std::size_t m_sUsedMemoryPoolSize;   //以使用内存的大小
    std::size_t m_sFreeMemoryPoolSize;   //可用内存的大小

    std::size_t m_sMemoryChunkSize;     //块(Chunk)的大小
    unsigned int m_uiMemoryChunkCount;  //块(Chunk)的数量
    unsigned int m_uiObjectCount;

    bool m_bSetMemoryData ; 
    std::size_t m_sMinimalMemorySizeToAllocate;


};

#endif

共2页 首页 上一页 1 2 下一页 尾页 跳转到
相关内容
赞助商链接