程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 簡明分析C/C++內存分配的解決方案(1)

簡明分析C/C++內存分配的解決方案(1)

編輯: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


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved