C++内存池的实现

1、这是一个C++编写的内存管理器,下载地址:https://github.com/mrYiXuYang/memory-manager我们主要学习他的思想,不应该拿来直接用!因为我认为他里面还存在一些小问题(作者很强、不可否认):(1)Vector的实现...

1、这是一个C++编写的内存管理器,下载地址:https://github.com/mrYiXuYang/memory-manager

我们主要学习他的思想,不应该拿来直接用!因为我认为他里面还存在一些小问题(作者很强、不可否认):

(1)Vector的实现还有一些问题;

(2)里面的锁我认为不太好;

(3)代码中223~232我认为还有一些问题。

(4)安全指针我认为保证了安全,降低了效率。

不过这不妨碍我们学习他的实现思路。

2、代码(添加了注释):

#include<memory>
#ifndef MEMORY_MANAGER
#define MEMORY_MANAGER
#else
#error has been defined 'MEMORY_MANAGER'
#endif // !MEMORY_MANAGER
#define OPERATOR_SIZE_64


namespace MyTool
{
#define M_LOG_EXCEPTION 0x01
#define M_LOG_MSG_HEAD 0x02
#define M_LOG_UFREE 0x04
#define M_LOG_FREE 0x08

#define M_DEFAULT_ADDLEN 1000
#define M_MAX_NAME_SIZE 32
	typedef unsigned char uchar,byte;
	typedef unsigned short ushort;
	typedef unsigned int  uint;
	typedef unsigned long ulong,bit32;
	typedef unsigned long long bit64;

	template<class T>
	class MVector
	{

	private:
		T *data;
		ulong now_count;
		ulong add_count;
		long length;
	public:
		typedef bool(*EraseFunc)(T&t);
		MVector()
		{
			//初始时默认申请1000个T类型的内存
			data = new T[M_DEFAULT_ADDLEN];
			//初始容量是1000
			now_count = M_DEFAULT_ADDLEN;
			//当容器满时,每次增加的数量
			add_count = M_DEFAULT_ADDLEN;
			//当前数据的个数
			length = 0;

		};

		//构造函数2,带初始化值
		MVector(ulong sz)
		{
			data = new T[sz];
			now_count = sz;
			add_count = sz;
			length = 0;
		};

		//构造函数3,拷贝构造函数
		MVector(const MVector&mv)
		{
			data = new T[mv.now_count];
			now_count = mv.now_count;
			add_count = mv.add_count;
			length = mv.length;
			memcpy(data, mv.data, sizeof(T)*length);
		};

		virtual~MVector()
		{
			if (!data)
			{
				delete[]data;
			}
			data = nullptr;
			length = 0;
			now_count = 0;
			add_count = 0;
		};
		void operator=(const MVector&mv)
		{
			if (!data)
				delete[]data;
			data = new T[mv.now_count];
			now_count = mv.now_count;
			add_count = mv.add_count;
			length = mv.length;
			memcpy(data, mv.data, sizeof(T)*length);
		};
		T& operator[](ulong posi)
		{
			return data[posi];
		};

		void Push_back(T&t)
		{
			if (length > now_count)
			{
				now_count += add_count;
				T *temp = new T[now_count];
				memcpy(temp, data, sizeof(T)*length);
				delete[]data;
				data = temp;
			}
			memcpy(&data[length], &t, sizeof(T));
			length++;

		};
		void Pop_back()
		{
			if (length < 0)
				return;
			length--;
		}
		bool Erase(EraseFunc fun)
		{
			if (length < 0)
				return false;
			for (long i = 0; i < length; i++)
			{
				if (fun(data[i]))
				{
					//开始 前移

					while (i + 1 < length)
					{
						memcpy(&data[i], &data[i + 1], sizeof(T));
						i++;
					}
					length--;
					return true;

				}
			}
			return false;
		}
		bool Erase(ulong posi)
		{
			if (posi >= length)
				return false;
			for (int i = posi; i + 1 < length; i++)
			{
				memcpy(&data[i], &data[i + 1], sizeof(T));
			}
			length--;
			return true;
		}
		ulong Length()
		{
			return length;
		}
	};
#ifdef OPERATOR_SIZE_64 //64位操作系统
#pragma pack(push)
#pragma pack(8)//8字节对齐

	//一种类型一个信息头
	typedef struct MemoryHeadMsg
	{
		//类型名
		char mhm_name[M_MAX_NAME_SIZE];
		//一个类型对应一个id
		uint mhm_id;
		//类型占用的字节数
		uint mhm_szof;
		//存储该类型申请的每个内存块的首地址
		MVector<byte*> *mhm_addr;
		//申请内存块的总大小
		ulong mhm_now_count;
		//每次内存块不足时,为内存块增加的大小
		ulong mhm_add_count;

	}MEMORYHEADMSG;

	//碎片的具体信息:首地址和长度
	typedef struct MemoryMsg
	{
		byte* mm_addr;
		uint count;
	}MEMORYMSG;

	//当前id下所有的碎片信息
	typedef struct MemoryMsgEx
	{
		uint mhm_id;
		MVector<MemoryMsg> *mme_msgs;
	}MEMORYMSGEX;

	typedef struct MemoryMsgDetailUnit
	{
		char name[M_MAX_NAME_SIZE];
		uint szof;
		int posi;
		ulong count;
	}MEMORYMSGDETAILUNIT;
#pragma pack(pop)
#endif // OPERATOR_SIZE_64

	int M_regis_struct(const char* name, uint szof, ulong count);
	int M_find_id(const char* name);
	byte* M_Malloc(uint id, ulong count);
	void M_free(byte* ptr);
	void M_get_msg(byte* ptr, MemoryMsgDetailUnit&msg);
	void M_quit();
	void M_printf_log();
	void M_init();

#define M_REGIS(type,count) M_regis_struct((#type),sizeof(type),(count))

#define M_FIND(type) M_find_id(#type)
#define M_NEW(type,count) (type*)M_Malloc(M_FIND(type),count)
#define M_FREE(ptr) M_free((byte*)(ptr))
#define M_MSG(ptr,msgstruct) M_get_msg((byte*)(ptr),msgstruct)
#define M_QUIT() M_quit()
#define M_PRINTF_LOG() M_printf_log()
#define M_INIT() M_init();

	template<class T>
	class MPtr
	{
	private:
		uint len;
		T* data;
	public:
		MPtr()
		{
			data = nullptr;
			len = 0;
		}
		MPtr(T* ptr)
		{
			if (ptr == nullptr)
			{
				data = nullptr;
				return;
			}
			MemoryMsgDetailUnit mmdu;
			M_MSG(ptr, mmdu);
			if (mmdu.posi < 0)
				return;
			if (mmdu.posi != 0)
				ptr -= (mmdu.posi);
			data = ptr;
			len = mmdu.count;
		}
		MPtr(MPtr&mmptr)
		{
			data = mmptr.data;
			len = mmptr.len;
		}
		~MPtr()
		{
			data = nullptr;
		}

		void Free()
		{
			M_FREE(data);
			data = nullptr;
		}

		T& operator[](uint posi)
		{
			if (posi >= len)
				//添加错误信息日志
				;
			return data[posi];
		}
		bool operator==(MPtr&mp)
		{
			if (mp.data == data)
				return true;
		}
		void operator=(MPtr&mp)
		{
			data = mp.data;
			len = mp.len;
		}
		class Iterator
		{
		private:
			T *data;
		public:
			Iterator()
			{
				data = nullptr;
			};
			Iterator(T*t)
			{
				data = t;
			};
			Iterator(Iterator&&it)
			{
				data = it.data;
			}
			Iterator(Iterator&it)
			{
				data = it.data;
			};
			
			T& operator*()const
			{
				if (data == nullptr)
				{
					T t;
					return t;
				}	
				return *data;
			};
			Iterator operator++()
			{
				if(data!=nullptr)
					data++;
				return *this;
			};
			Iterator operator--()
			{
				if (data != nullptr)
					data--;
				return *this;
			};

			Iterator operator++(int)
			{
				Iterator it = *this;
				if (data != nullptr)
					data++;
				return it;
			};
			Iterator operator--(int)
			{
				Iterator it = *this;
				if (data != nullptr)
					data--;
				return it;
			};

			~Iterator() {};

			bool operator==(Iterator&it)
			{
				if (it.data == data)
					return true;
				return false;
			};
			bool operator==(Iterator&&it)
			{
				if (it.data == data)
					return true;
				return false;
			};
			bool operator!=(Iterator&it)
			{
				if (it.data != data)
					return true;
				return false;
			};
			bool operator!=(Iterator&&it)
			{
				if (it.data != data)
					return true;
				return false;
			};
			void operator=(Iterator&it)
			{
				data = it.data;
			};
			void operator=(Iterator&&it)
			{
				data = it.data;
			};
		};
		Iterator Start()
		{
			Iterator it(data);
			
			return it;
		}
		Iterator End()
		{
			if (data == nullptr)
			{
				Iterator it(nullptr);
				return it;

			}

			T* temp = data;
			MemoryMsgDetailUnit mmdu;
			M_MSG(temp, mmdu);
			if (mmdu.posi < 0)
				//add exception log
				;
			temp += (mmdu.count);
			Iterator it(temp);
			return it;
		}
	};

}
#include<atomic>
#include<stdio.h>
#include<exception>
#include"manager.h"




namespace MyTool
{

	struct ComMsg
	{
		uint posi;
		int cut;
	};

	//存放注册头信息
	  static MVector<MemoryHeadMsg> *mhm_list;
	  //存放碎片信息(未被使用的内存块)
	  static MVector<MemoryMsgEx> *mme_free_list;
	  //存放未释放内存信息(正在使用的内存块)
	  static MVector<MemoryMsgEx> *mme_ufree_list;
	 
	
	static std::atomic_char mhm_list_flag = 1;
	static  std::atomic_char mme_free_list_flag = 1;
	static  std::atomic_char mme_ufree_list_flag = 1;

	//初始化和退出标志
	bool initflag = false;
	std::atomic_bool quit_flag=false;

#define LOCK(arg) do{arg##_flag--;while(arg##_flag<0){};}while(0);
#define ULOCK(arg) do{arg##_flag++;}while(0);

	bool str_equal(const char* str1, const char*str2)
	{
		if (str1 == str2)
			return true;
		uint len1 = strlen(str1);
		uint len2 = strlen(str2);
		if (len1 != len2)
			return false;
		else if (str1 == nullptr || str2 == nullptr||len1==0)
			return false;
		for (int i = 0; i < len1; i++)
			if (str1[i] != str2[i])
				return false;
		return true;
	}

	int M_find_id(const char* name)
	{
		if (quit_flag)
			return -1;
		LOCK(mhm_list);
		for (int i = 0; i < mhm_list->Length(); i++)
		{
			if (str_equal(mhm_list->operator[](i).mhm_name, name))
			{
				ULOCK(mhm_list);
				return i;
				
			}
		}
		ULOCK(mhm_list);
		return -1;
	}

	int M_regis_struct(const char* name, uint szof, ulong count)
	{
		//退出标志
		if (quit_flag)
		{
			return -1;
		}

		//当前类型能找到对应的Id,说明已经注册过,返回
		if (M_find_id(name) != -1)
		{
			return -1;
		}

		LOCK(mhm_list)LOCK(mme_free_list)LOCK(mme_ufree_list);

		//注册内存信息头,一种类型对应一个内存信息头
		MemoryHeadMsg msg;
		msg.mhm_add_count = count;
		msg.mhm_szof = szof;
		msg.mhm_now_count = count;
		strcpy_s(msg.mhm_name, name);
		msg.mhm_id = mhm_list->Length();

		bit64 tlen = (bit64)szof * count; 
		byte* temp = nullptr;
		try
		{
			 temp = new byte[tlen];
		}
		catch(std::exception a)
		{
			return -1;
		}

		msg.mhm_addr = new MVector<byte*>(10);
		msg.mhm_addr->Push_back(temp);

		//存储注册头信息
		mhm_list->Push_back(msg);

		//注册相应的空间碎片信息(没使用的内存信息)
		MemoryMsgEx mme;
		mme.mhm_id = msg.mhm_id;                       //某一数据类型
		mme.mme_msgs = new MVector<MemoryMsg>(count);  //该数据类型的碎片信息

		//具体某一块碎片信息,注册时只有一块连续的内存块
		MemoryMsg mm;
		mm.count = msg.mhm_now_count; //该碎片的长度
		mm.mm_addr = temp;            //该碎片的首地址

		mme.mme_msgs->Push_back(mm);
		mme_free_list->Push_back(mme);

		//注册相应的未释放内存信息(正在使用的内存块,注册时还没有)
		mme.mhm_id = msg.mhm_id;
		mme.mme_msgs= new MVector<MemoryMsg>(count);
		mme_ufree_list->Push_back(mme);

		ULOCK(mhm_list)ULOCK(mme_free_list)ULOCK(mme_ufree_list);

		return msg.mhm_id;

	}

	byte* M_Malloc(uint id, ulong count)
	{
		if (quit_flag)
		{
			return nullptr;
		}
		LOCK(mhm_list)LOCK(mme_free_list)LOCK(mme_ufree_list);

		//该类型id号不在碎片信息中
		if (id >= mme_free_list->Length())
		{
			ULOCK(mhm_list)ULOCK(mme_free_list)ULOCK(mme_ufree_list);

			return nullptr;
		}

		//获取该类型空间碎片表
		MemoryMsgEx &mme = mme_free_list->operator[](id);
		
		byte* result=nullptr;
		ComMsg cm;
		ComMsg temp = { -1,-1 };

		//内存位置索引
		cm.posi = 0;
		//当前类型第一个碎片信息内存量与将要申请的内存差值
		cm.cut = mme.mme_msgs->operator[](0).count - count;

		//在所有碎片中进行循环查找
		for (int i = 1; i < mme.mme_msgs->Length(); i++)
		{
			//有碎片信息内存与将要申请的内存相等(最好的情况)
			if (cm.cut == 0)
				break;

			//选取一个碎片用于新申请的内存,选取规则:找内存差值最小的碎片
			MemoryMsg &mm = mme.mme_msgs->operator[](i);
			temp.posi = i;
			temp.cut = mm.count - count;
			if (temp.cut == 0)
			{
				cm.cut = 0;
				cm.posi = i;
				break;
			}
			else if (temp.cut > 0)
			{
				//如果第i-1个碎片信息不够申请内存,将第i个作为基准值
				if (cm.cut < 0)
					memcpy(&cm, &temp, sizeof(ComMsg));
				else
					if(temp.cut<cm.cut)//第i个差值与第i-1个差值比较
						memcpy(&cm, &temp, sizeof(ComMsg));
			}
		}

		// 如果空间碎片不足长度,向系统申请新的空间
		if (cm.cut < 0)
		{
			MemoryHeadMsg &mhm = mhm_list->operator[](id);
			ulong newlen = mhm.mhm_add_count*mhm.mhm_szof;
			ulong adlen = newlen;
			while (newlen < count*mhm.mhm_szof)
			{
				newlen += adlen;
			}
			byte *temp = new byte[newlen];
			mhm.mhm_addr->Push_back(temp);


			result = temp;

			//添加新的空间碎片
			MemoryMsg newmm;
			//分配完成之后剩余碎片首地址:向操作系统申请的总内存块首地址 + 应用程序申请的字节长度 + 1
			newmm.mm_addr = temp + count*mhm.mhm_szof+1;
			newmm.count = newlen/mhm.mhm_szof-count;

			if(newmm.count)
				mme_free_list->operator[](id).mme_msgs->Push_back(newmm);
		}
		else if (cm.cut == 0)//有碎片内存正好与要申请的内存相等
		{
			result = mme.mme_msgs->operator[](cm.posi).mm_addr;
			//删除碎片信息
			mme.mme_msgs->Erase(cm.posi);
		}
		else//找到一个最合适的内存碎片:差值最小的碎片用于分配
		{
			result = mme.mme_msgs->operator[](cm.posi).mm_addr;
			//取出碎片,并修改碎片信息
			MemoryMsg&mm = mme.mme_msgs->operator[](cm.posi);
			MemoryHeadMsg &mhm = mhm_list->operator[](id);
			mm.mm_addr = mm.mm_addr + count*mhm.mhm_szof+1;
			mm.count = cm.cut;
			//???????????????此处应该将分配后剩余碎片信息添加到:mme_free_list????????????????????????????????
		}

		//result = cm.cut < 0 ? result : mme.mme_msgs->operator[](cm.posi).mm_addr;

		//加入当前活跃(正在使用的)内存信息
		MemoryMsg umm;
		umm.count = count;
		umm.mm_addr = result;
		mme_ufree_list->operator[](id).mme_msgs->Push_back(umm);

		ULOCK(mhm_list)ULOCK(mme_free_list)ULOCK(mme_ufree_list);

		return result;
	}

	MemoryMsgEx* find_msg(byte* ptr,int *posi)
	{
		if (quit_flag)
			return nullptr;
		LOCK(mhm_list)LOCK(mme_free_list)LOCK(mme_ufree_list);
		for (int i = 0; i < mme_ufree_list->Length(); i++)
		{
			MemoryMsgEx& msg = mme_ufree_list->operator[](i);
			for (int j = 0; j < msg.mme_msgs->Length(); j++)
			{
				MemoryMsg &mm = msg.mme_msgs->operator[](j);
				if (mm.mm_addr == ptr)
				{
					*posi = j;
					ULOCK(mhm_list)ULOCK(mme_free_list)ULOCK(mme_ufree_list);
					return &msg;
				}
			}
		}
		ULOCK(mhm_list)ULOCK(mme_free_list)ULOCK(mme_ufree_list);
		*posi = -1;
		return nullptr;
	}

	void M_free(byte* ptr)
	{
		if (quit_flag)
			return;
		int posi;
		
		MemoryMsgEx* msgptr = find_msg(ptr, &posi);
		LOCK(mhm_list)LOCK(mme_free_list)LOCK(mme_ufree_list);
		if (msgptr == nullptr)
		{
			ULOCK(mhm_list)ULOCK(mme_free_list)ULOCK(mme_ufree_list);
			return;
		}
		MemoryMsg &mm=msgptr->mme_msgs->operator[](posi);

		//加入到空间碎片信息 或者 合并碎片空间信息

		MemoryMsgEx&mex = mme_free_list->operator[](msgptr->mhm_id);
		uint szof = mhm_list->operator[](msgptr->mhm_id).mhm_szof;
		bool flag = false;
		//判断是否需要整合碎片
		for (int i = 0; i < mex.mme_msgs->Length(); i++)
		{
			MemoryMsg &temp = mex.mme_msgs->operator[](i);
			if (temp.mm_addr == (mm.mm_addr + (mm.count*szof))+1)//头尾相接
			{
				temp.mm_addr = mm.mm_addr;
				
				temp.count += mm.count;

				flag = true;
				break;
			}
			else if ((temp.mm_addr + (temp.count*szof))+1 == mm.mm_addr)//尾头相接
			{
				temp.count += mm.count;
				flag = true;
				break;
			}
		}
		if (!flag)//不存在整合碎片的情况
		{
			mex.mme_msgs->Push_back(mm);
		}
		

		//从动态的内存信息表移除
		bool f=mme_ufree_list->operator[](msgptr->mhm_id).mme_msgs->Erase(posi);

		int i = 0;


		ULOCK(mhm_list)ULOCK(mme_free_list)ULOCK(mme_ufree_list);
	}

	void M_get_msg(byte* ptr,MemoryMsgDetailUnit&msg)
	{
		if (quit_flag)
			return;
		LOCK(mhm_list)LOCK(mme_free_list)LOCK(mme_ufree_list);
		for (int i = 0; i < mme_ufree_list->Length(); i++)
		{
			MEMORYMSGEX &mex = mme_ufree_list->operator[](i);
			for (int j = 0; j < mex.mme_msgs->Length(); j++)
			{
				MemoryMsg &mm = mex.mme_msgs->operator[](j);
				byte* end = mm.mm_addr + mhm_list->operator[](mex.mhm_id).mhm_szof*mm.count;
				if (ptr >= mm.mm_addr&&ptr <= end)
				{
					memcpy(msg.name, mhm_list->operator[](mex.mhm_id).mhm_name, M_MAX_NAME_SIZE);
					msg.szof = mhm_list->operator[](mex.mhm_id).mhm_szof;
					int nn = ptr - mm.mm_addr;
					msg.posi = (ptr - mm.mm_addr) / 4;
					msg.count = mm.count;
					ULOCK(mhm_list)ULOCK(mme_free_list)ULOCK(mme_ufree_list);
					return;
				}
			}
		}
		msg.posi = -1;
		ULOCK(mhm_list)ULOCK(mme_free_list)ULOCK(mme_ufree_list);
	}

	void M_quit()
	{
		if (quit_flag)
			return;
		LOCK(mhm_list)LOCK(mme_free_list)LOCK(mme_ufree_list);
		//删除总空间
		for (int i = 0; i < mhm_list->Length(); i++)
		{
			MemoryHeadMsg &mhm = mhm_list->operator[](i);
			for (int j = 0; j < mhm.mhm_addr->Length(); j++)
			{
				byte* &temp = mhm.mhm_addr->operator[](j);
				if (temp)
					delete[]temp;
				temp = nullptr;
			}
			delete mhm.mhm_addr;
		}
		//释放碎片信息
		for (int i = 0; i < mme_free_list->Length(); i++)
		{
			MemoryMsgEx &mme = mme_free_list->operator[](i);
			for (int j = 0; j < mme.mme_msgs->Length(); j++)
			{
				//添加日志信息

			}
			delete mme.mme_msgs;
		}
		//释放活跃内存信息

		for (int i = 0; i < mme_ufree_list->Length(); i++)
		{
			MemoryMsgEx &mme = mme_ufree_list->operator[](i);
			for (int j = 0; j < mme.mme_msgs->Length(); j++)
			{
				//添加日志信息

			}
			delete mme.mme_msgs;
		}

		delete mhm_list, mhm_list = nullptr;
		delete mme_free_list, mme_free_list = nullptr;
		delete mme_ufree_list, mme_ufree_list = nullptr;

		ULOCK(mhm_list)ULOCK(mme_free_list)ULOCK(mme_ufree_list);
		quit_flag = true;
	}

	void M_init()
	{
		LOCK(mhm_list)LOCK(mme_free_list)LOCK(mme_ufree_list);
		if (!initflag)
		{
			mhm_list = new MVector<MemoryHeadMsg>();
			mme_free_list = new  MVector<MemoryMsgEx>();
			mme_ufree_list = new  MVector<MemoryMsgEx>();
			initflag = true;
		}
		ULOCK(mhm_list)ULOCK(mme_free_list)ULOCK(mme_ufree_list);
	}

	void M_printf_log()
	{

	}
}
// MemoryPoolTest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include"manager.h"

using namespace MyTool;

int main()
{
	M_INIT();
	M_REGIS(int, 1024);

	int* a = M_NEW(int, 10);

	for (int i = 0; i < 10; i++)//不安全操作
		a[i] = i;

	MPtr<int> mp(a + 4);
	for (MPtr<int>::Iterator it = mp.Start(); it != mp.End(); it++)//安全操作
	{
		printf(" %d ", *it);
	}
	//安全操作
	mp[4] = 10;
	printf("mp[4]:%d ", mp[4]);
	mp.Free();

	M_QUIT();
	getchar();
	return 0;
}


 

  • 点赞
  • 收藏
  • 分享
    • 文章举报
米小鸢 发布了415 篇原创文章 · 获赞 123 · 访问量 64万+ 他的留言板 关注

本文标题为:C++内存池的实现