ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

C++内存池的实现

2020-02-27 15:06:17  阅读:277  来源: 互联网

标签:count mhm return 实现 list C++ 内存 mme data


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万+ 他的留言板 关注

标签:count,mhm,return,实现,list,C++,内存,mme,data
来源: https://blog.csdn.net/u012372584/article/details/104536468

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有