C++实现内存池

本文档详细介绍了如何在C++中实现内存池,包括MemoryPool.cpp中的MemoryBlock结构和相关实现,以及如何在main.cpp中有效使用内存池。通过这种方式,可以优化内存分配和释放的效率,提高程序性能。
摘要由CSDN通过智能技术生成

C++实现内存池


参考:https://www.cnblogs.com/dylantsou/archive/2012/05/13/2498491.html
详细原理可以上面的链接。
内存池是由block链表实现,每个block(块)链表上挂载了多个unit (单元)。
本人在链接基础上封装了block 成员变量。并且block 中的unit 采用链表方式,一个unit 指向 下一个可用的unit。优化了内存越界bug。干掉了对USHORT 的依赖。
使用起来更加优雅,简洁,明了
内存池:
MemoryPool.h

#pragma once
#include <stdlib.h>
#include "MemoryBlock.h"

class MemoryPool
{
public:
	//_unitCount 每个block下 unit个数
	MemoryPool(int _unitSize, int _unitCount = 16);
	~MemoryPool();

	void *Alloc();
	void Free(void *);

private:
	int				unitSize;	//单元大小
	int				unitCount;	//多少个单元

	MemoryBlock*	pBlock;		//内存链表
};



MemoryPool.cpp:

#include "MemoryPool.h"
#define  MEMPOOL_ALIGNMENT 8            //对齐长度

#include <stdio.h>
#include <iostream>

MemoryPool::MemoryPool(int _unitSize, int _unitCount)
{
	unitSize = _unitSize;
	unitCount = _unitCount;

	pBlock = NULL;
	if (unitSize > 4)
		unitSize = (unitSize + (MEMPOOL_ALIGNMENT - 1)) & ~(MEMPOOL_ALIGNMENT - 1);
	else if (unitSize < 2)
		unitSize = 2;
	else
		unitSize = 4;
}

MemoryPool::~MemoryPool()
{
	MemoryBlock *p = pBlock;
	MemoryBlock *temp;
	while (p)
	{
		temp = p;
		p = p->pNext;
		delete temp;
	}
}

void * MemoryPool::Alloc()
{
	//第一次为空,分配第一个block
	if (pBlock == NULL)
	{
		std::cout << "first new block " << std::endl;
		pBlock = (MemoryBlock *)new(unitSize, unitCount) MemoryBlock(unitSize, unitCount);
		if (pBlock == NULL)
		{
			std::cout << "error new block failed" << std::endl;
			return NULL;
		}
		return pBlock->mallocUnit();
	}

	//找到第一个 有空闲的 block
	MemoryBlock *tempBlock = pBlock;
	while (tempBlock && tempBlock->memFull())
	{
		tempBlock = tempBlock->pNext;
	}

	//若 没有空闲block,再次分配一个block
	if (tempBlock == NULL)
	{
		std::cout << "next new block " << std::endl;
		tempBlock = (MemoryBlock *)new(unitSize, unitCount) MemoryBlock(unitSize, unitCount);
		if (tempBlock == NULL)
		{
			std::cout << "error new block failed" << std::endl;
			return NULL;
		}

		tempBlock->pNext = pBlock;
		pBlock = tempBlock;
	}
	
	return tempBlock->mallocUnit();
}

void MemoryPool::Free(void * pFree)
{
	MemoryBlock * tempBlock = pBlock;
	MemoryBlock * preBlock = tempBlock;

	while (tempBlock != NULL && !tempBlock->inBlock(pFree))
	{
		preBlock = tempBlock;
		tempBlock = tempBlock->pNext;
	}

	if (tempBlock == NULL)
	{
		printf("Errror cannot find mem \n");
		return;
	}

	printf("free mem ok\n");
	tempBlock->freeUnit(pFree);

	// 若整个block都是空闲,则回收这个block
	if (tempBlock->memEmpty())
	{
		if (tempBlock == pBlock)
		{
			pBlock = pBlock->pNext;
		}
		else
		{
			preBlock->pNext = tempBlock->pNext;
		}

		printf("delete block \n");
		delete tempBlock;
	}
	else //将此block 放置到链表首
	{
		if (tempBlock = pBlock)
		{
			return;
		}

		preBlock->pNext = tempBlock->pNext;
		tempBlock->pNext = pBlock;
		pBlock = tempBlock;
	}
}	

block实现:
MemoryBlock.h

#pragma once

#include <stdlib.h>

class MemoryBlock
{
public:
	MemoryBlock(int _nUnitSize, int _unitCount);
	~MemoryBlock();

	static void *  operator new(size_t, int nUnitSize, int nUnitAmount);
	static void    operator delete(void *, int nUnitSize, int nUnitAmount){}
	static void    operator delete(void *pBlock);

public:
	void *mallocUnit();
	bool freeUnit(void *pFree);

	//是否所有单元装满了
	bool memFull() { return nFree == 0; }

	//是否所有单元为空
	bool memEmpty();

	bool inBlock(void *pFree);

	MemoryBlock*	pNext;		//下一个block

private:
	int				unitSize;	//单元大小
	int				unitCount;	//单元数量
	int				totalSize;		// 该块内存大小, 字节
	int				nFree;		// 多少个单元
	void *			nextPtr;	// 当前可用单元 地址
	char			aData[1];	// 分配单元起始位置
};

MemoryBlock.cpp

#include "MemoryBlock.h"
#include <iostream>

//区分32位和64位
#ifdef _WIN64 
#define PTR_TYPE unsigned long long
#else
#define PTR_TYPE unsigned long
#endif

//将 h 前几个字节存放 下一个指针的值 
static void setNextUnitPointer(void *h, void *pNextUnit)
{
	*(PTR_TYPE *)(h) = (PTR_TYPE)(pNextUnit);
}

//取出 h 指针内存放的 下一指针值
static void getNextUnitPointer(void *h, void **pNextUnit)
{
	*pNextUnit = (void *) (*(PTR_TYPE *)(h));
}

MemoryBlock::MemoryBlock(int _nUnitSize, int _unitCount)
	: unitSize(_nUnitSize)
	, unitCount(_unitCount)
	, totalSize(unitCount * unitSize)
	, nFree(unitCount)
	, pNext(NULL)
{
	nextPtr = (void *)aData;
	char *ptr = aData;

	// 每个单元前几个字节存放下一个单元的地址, 其实是一个链表
	for (int i = 0; i < unitCount - 1; i++)
	{
		setNextUnitPointer(ptr + i*unitSize, ptr + i * unitSize + unitSize);
	}
}

MemoryBlock::~MemoryBlock()
{
}

void *  MemoryBlock::operator new(size_t, int nUnitSize, int unitCount)
{
	return ::operator new(sizeof(MemoryBlock) + nUnitSize * unitCount);
}

void    MemoryBlock::operator delete(void *pBlock)
{
	::operator delete(pBlock);
}

void * MemoryBlock::mallocUnit()
{
	void *pFree = nextPtr;

	getNextUnitPointer(nextPtr, &nextPtr);
	nFree--;

	std::cout << "new unit , free =  " << nFree << std::endl;
	return pFree;
}

bool MemoryBlock::freeUnit(void *pFree)
{
	setNextUnitPointer(pFree, nextPtr);
	nextPtr = pFree;

	nFree++;
	return true;
}

bool MemoryBlock::memEmpty()
{
	return (totalSize == nFree * unitSize);
}

bool MemoryBlock::inBlock(void *pFree)
{
	return pFree >= aData  &&  pFree <= aData + totalSize;
}

如何使用:
main.cpp


#include <stdio.h>
#include "MemoryBlock.h"
#include "MemoryPool.h"

class CTest
{
public:
	CTest(int num) { data1 = data2 = num; };
	~CTest() {};
	void*       operator new (size_t);
	void        operator delete(void* pTest);
public:

	int         data1;
	int         data2;
};

static MemoryPool Pool(sizeof(CTest));

void CTest::operator delete(void* pTest)
{
	Pool.Free(pTest);
}

void* CTest::operator new(size_t)
{
	return (CTest*)Pool.Alloc();
}

#include <vector>
int main()
{
	std::vector<CTest *> lists;
	for (int i = 0; i < 50; i++)
	{
		CTest* pTest = new CTest(i);
		printf("%d \n", pTest->data2);
		lists.push_back(pTest);
	}
	
	for (auto ptr : lists)
	{
		delete ptr;
	}
	lists.clear();
	
	for (int i = 50; i < 100; i++)
	{
		CTest* pTest = new CTest(i);
		printf("%d \n", pTest->data2);
		lists.push_back(pTest);
	}
	for (auto ptr : lists)
	{
		delete ptr;
	}
	lists.clear();
	
	while (true)
	{
	}
}

效果如图:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值