C++内存池的实现
作者:互联网
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