c++内存池(简单)

来源:互联网 发布:淘宝网证书错误怎么办 编辑:程序博客网 时间:2024/06/05 15:26

简要说明基本原理:对申请的小块内存进行内存管理,每个管理队列仅管理当前打小的内存块。如果当前大小内存块不足,就访问进程堆分块一块大内存,默认4K,然后初始化完毕后,供申请者使用。

本人将小内存块划分为

16字节,

32字节,

48字节,

64字节,

80字节,

96字节,

112字节,

128字节,

144字节,

160字节,

176字节,

192字节,

208字节,

224字节,

240字节,

256字节,

如果分配以上大小的内存块,将从对应的管理类CMemoryPool分配内存块。大于256的内存块直接从进程堆分配。


下面直接上代码:

#ifndef _IMEMORYBLOCK_H_#define _IMEMORYBLOCK_H_namespace MemPool{typedef unsigned int size_t;#define DEBUG_SWITCH_INIT_MEMORYtrue//debug调试内存初始化#define MEMORY_BLOCK_MASK((size_t)0x59EF0000)#define MEMORY_BLOCK_INUSE((size_t)0x80000000)#define MEMORY_BLOCK_LENGTH_SECTION((size_t)0x0000FFFF)#define SET_UNUSE_BLOCK_HEAD(length)(((size_t)length) | MEMORY_BLOCK_MASK)#define EXCHANGE_BLOCK_INUSE(head)(((size_t)head) |= MEMORY_BLOCK_INUSE)#define EXCHANGE_BLOCK_UNUSE(head)(((size_t)head) &= ~MEMORY_BLOCK_INUSE)#define GET_BLOCK_LENGTH(head)(((size_t)head) & MEMORY_BLOCK_LENGTH_SECTION)#define IS_INUSE(head)(bool)(((size_t)head) & MEMORY_BLOCK_INUSE)#define IS_MASK_OK(head)(MEMORY_BLOCK_MASK == (((size_t)head) & ~(MEMORY_BLOCK_INUSE|MEMORY_BLOCK_LENGTH_SECTION)))// 内存块struct malloc_block{size_t _head;//当前块数据malloc_block* _next;//下一块空闲内存块地址[空闲的时候使用]};struct malloc_chunk{void *_ptr;//申请的内存单元头指针size_t _chunkSize;//当前内存单元总大小size_t _blockSize;//每个内存块大小unsigned int _blockCount;//内存块数量malloc_block* _blockHead;//头malloc_block* _blockFoot;//尾malloc_chunk* _next;//下一个内存单元指针// 构造和析构void construct();void deconstruct();// 构建内存块bool InitializeChunk(size_t chunkSize = 0x1000, size_t blockSize = 0x10);// 联合内存单元数据块// 参  数:传入内存块链表尾指针// 返回值:返回新的内存块连接表尾指针malloc_block *JoinChunk(malloc_block *&head);};class CChunkPool{public:CChunkPool();~CChunkPool();// 初始化内存块// size_t chunkSize = 0x1000//默认内存单元大小4K// size_t blockSize = 0x10,//默认块内存大小16字节,可用内存12字节(头head占用4字节)bool InitializeMallocChunk(size_t chunkSize = 0x1000, size_t blockSize = 0x10);// 申请内存块void *malloc();// 释放内存块void free(void *ptr);// 分配内存从系统Heapvoid realloc();private:size_t m_blockSize;size_t m_chunkSize;malloc_chunk* m_pMallocChunk;//内存单元Chunk列表malloc_block* m_pBlockHead;//头malloc_block* m_pBlockFoot;//尾};// 内存单元池数量#define CHUNK_POOL_SIZE16// 最小内存块大小#define MIN_BLOCK_SIZE16// 内存大小获取ChunkPool索引#define GET_CHUNKPOOL_INDEX(length)(size_t)( ( length + sizeof(size_t) - 1 ) / MIN_BLOCK_SIZE)class IMemoryPool{public:virtual ~IMemoryPool() {}virtual void *malloc(size_t size) = 0;virtual void free(void *p, size_t size) = 0;};class CMemoryPool : public IMemoryPool{public:CMemoryPool();~CMemoryPool();// 初始化内存池bool InitMemoryPool();void *malloc(size_t size);void free(void *p, size_t size = 0);private:CChunkPool m_pChunkPool[CHUNK_POOL_SIZE];//malloc_chunk* m_pHeapChunk;//进程堆使用内存链表};};#endif



#include "stdafx.h"#include "IMemoryBlock.h"namespace MemPool{#define mem2block(mem)(malloc_block*)((char*)mem - sizeof(size_t))#define block2mem(b)(void*)((char*)b + sizeof(size_t))void malloc_chunk::construct(){_ptr = NULL;_chunkSize = 0;_blockSize = 0;_blockCount = 0;_blockHead = NULL;_blockFoot = NULL;_next = NULL;}void malloc_chunk::deconstruct(){::free(_ptr);_ptr = NULL;_chunkSize = 0;_blockSize = 0;_blockCount = 0;_blockHead = NULL;_blockFoot = NULL;_next = NULL;}bool malloc_chunk::InitializeChunk( size_t chunkSize /*= 0x1000*/, size_t blockSize /*= 0x10*/ ){void *ptr = ::malloc(chunkSize);if (NULL == ptr){return false;}if (DEBUG_SWITCH_INIT_MEMORY)//debug调试{memset(ptr, 0, chunkSize);}_ptr = ptr;_chunkSize = chunkSize;_blockSize = blockSize;_blockCount = 0;_blockHead = NULL;_blockFoot = NULL;// 头内存块malloc_block* prevBlock = NULL;malloc_block* currentBlock = NULL;size_t haveInitSize = 0;// 循环构造内存块while (haveInitSize + _blockSize <= _chunkSize){if (NULL == currentBlock){// 设置头内存块指针currentBlock = _blockHead = (malloc_block*)ptr;}else{// 移动到下一个内存块currentBlock = (malloc_block*)((char*)currentBlock + _blockSize);}// 已初始化内存大小累加haveInitSize += _blockSize;++_blockCount;//内存块数量累加currentBlock->_head = SET_UNUSE_BLOCK_HEAD(_blockSize);currentBlock->_next = NULL;if (NULL != prevBlock){prevBlock->_next = currentBlock;}prevBlock = currentBlock;}// 设置尾内存块指针_blockFoot = currentBlock;return true;}malloc_block * malloc_chunk::JoinChunk( malloc_block *&head ){head = _blockHead;return _blockFoot;}MemPool::CChunkPool::CChunkPool(){m_blockSize = 0;m_chunkSize = 0;m_pMallocChunk = NULL;m_pBlockHead = NULL;m_pBlockFoot = NULL;}MemPool::CChunkPool::~CChunkPool(){m_blockSize = 0;m_chunkSize = 0;while (NULL != m_pMallocChunk){malloc_chunk* pDelChunk = m_pMallocChunk;m_pMallocChunk = m_pMallocChunk->_next;pDelChunk->deconstruct();::free(pDelChunk);pDelChunk = NULL;}m_pBlockHead = NULL;m_pBlockFoot = NULL;}bool CChunkPool::InitializeMallocChunk( size_t chunkSize /*= 0x1000*/, size_t blockSize /*= 0x10*/ ){m_chunkSize = chunkSize;m_blockSize = blockSize;return true;}void * CChunkPool::malloc( void ){if (NULL == m_pBlockHead){realloc();}if (NULL == m_pBlockHead){// 内存申请失败return NULL;}malloc_block* pMallocBlock = m_pBlockHead;m_pBlockHead = m_pBlockHead->_next;if (NULL == m_pBlockHead){m_pBlockFoot = NULL;}// 重置数据EXCHANGE_BLOCK_INUSE(pMallocBlock->_head);pMallocBlock->_next = NULL;return block2mem(pMallocBlock);}void CChunkPool::free( void *ptr ){if (NULL == ptr) return ;malloc_block* pDelMallocBlock = mem2block(ptr);if (!IS_MASK_OK(pDelMallocBlock->_head)){// 校验内存块错误return ;}if (m_blockSize != GET_BLOCK_LENGTH(pDelMallocBlock->_head)){// 内存块释放长度问题return ;}if (DEBUG_SWITCH_INIT_MEMORY)//debug调试{memset(ptr, 0, m_blockSize - sizeof(size_t));}// 更改使用状态EXCHANGE_BLOCK_UNUSE(pDelMallocBlock->_head);pDelMallocBlock->_next = m_pBlockHead;m_pBlockHead = pDelMallocBlock;// 可以尝试释放内存单元}void CChunkPool::realloc(){// 从heap分配内存malloc_chunk *pNewMallocChunk = /*new malloc_chunk*/(malloc_chunk *)::malloc(sizeof(malloc_chunk));if (NULL == pNewMallocChunk){return ;}pNewMallocChunk->construct();if (!pNewMallocChunk->InitializeChunk(m_chunkSize, m_blockSize)){pNewMallocChunk->deconstruct();::free(pNewMallocChunk);pNewMallocChunk = NULL;return ;}if (NULL == m_pMallocChunk){m_pMallocChunk = pNewMallocChunk;}else{// 新创建内存单元链接到链表头部pNewMallocChunk->_next = m_pMallocChunk;m_pMallocChunk = pNewMallocChunk;}// Join内存块链表if (NULL == m_pBlockHead){m_pBlockFoot = pNewMallocChunk->JoinChunk(m_pBlockHead);}else{m_pBlockFoot = pNewMallocChunk->JoinChunk(m_pBlockFoot);}}CMemoryPool::CMemoryPool(){}CMemoryPool::~CMemoryPool(){}bool CMemoryPool::InitMemoryPool(){for (int i=0; i<CHUNK_POOL_SIZE; ++i){m_pChunkPool[i].InitializeMallocChunk(0x1000, MIN_BLOCK_SIZE*(i+1));}return true;}void * CMemoryPool::malloc( size_t size ){size_t index = GET_CHUNKPOOL_INDEX(size);if (index < CHUNK_POOL_SIZE){return m_pChunkPool[index].malloc();}else{// 从进程堆分配内存return ::malloc(size);}}void CMemoryPool::free( void *p, size_t size ){if (NULL == p)return ;malloc_block* pMallocBlock = mem2block(p);size_t length = GET_BLOCK_LENGTH(pMallocBlock->_head);size_t index = GET_CHUNKPOOL_INDEX(length-sizeof(size_t));if (index < CHUNK_POOL_SIZE){m_pChunkPool[index].free(p);}else{// 从进程堆分配内存::free(p);p = NULL;}}}