c++内存池(简单)

简要说明基本原理:对申请的小块内存进行内存管理,每个管理队列仅管理当前打小的内存块。如果当前大小内存块不足,就访问进程堆分块一块大内存,默认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;
		}
	}

}


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值