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;
}


C++内存池的实现教程米小鸢发布了415 篇原创文章 · 获赞 123 · 访问量 64万+ 他的留言板 关注

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

相关文章推荐

添加新评论,含*的栏目为必填