简要说明基本原理:对申请的小块内存进行内存管理,每个管理队列仅管理当前打小的内存块。如果当前大小内存块不足,就访问进程堆分块一块大内存,默认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_MEMORY true //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);
// 分配内存从系统Heap
void 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_SIZE 16
// 最小内存块大小
#define MIN_BLOCK_SIZE 16
// 内存大小获取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;
}
}
}