C++实现一个简易的内存池分配器

版权声明:本文为博主原创文章,若需转载,请发邮件至oyoung_2012@hotmail.com获得许可,否则后果自负 https://blog.csdn.net/oyoung_2012/article/details/78874869

闲来无事突发奇想写个简单的内存分配器, 考虑到C++ 中的new 操作符可以很轻易的分配内存, delete释放也很方便,但是如果使用C++编写单片机的代码,就不能这样轻易使用new/delete了。其实基于C++的强大,完全可以自己实现new/delete的重载,使用到自己的内存分配。 使用自己的内存分配的好处是,可以在某个已知可用的内存块上随意的进行小块内存的动态分配与释放,这样的话,不仅可以是内存的使用更灵活,也更高效

此篇博文中所涉及的内存分配算法并不保证完全的绝对的高效,但是在平时动态使用内存块的时候却也能提供一定的方便(即使new/delete可用)

此内存块内存分配算法的时间与已分配内存块数目和需要分配内存块大小有关, 释放时间复杂度O(1)

struct MNode
{
    unsigned size;
    MNode *prev;
    MNode *next;
    char data[0];
};
class MMU
{
public:
    MMU(void * base, unsigned len): base((int *)base), length(len) { init();}
    void *alloc(unsigned size) {
        unsigned nsize = sizeof(MNode); //节点大小
        unsigned bsize = (size + nsize + 3) & (~0x03u);   //要分配的内存块大小, 保证四字节对齐
        MNode *ph = head;
        while(ph->next != nullptr) {  //没有到末尾则循环查找
            unsigned fsize = (unsigned long)ph->next - (unsigned long long)ph; //计算两个节点中间的空间
            fsize -= nsize + ph->size;  //除去MNode节点本身大小和分配的大小总和后剩下的空间,为空闲空间
            if(fsize > bsize) break;  //空闲空间找到了,停止循环
            ph = ph->next; // 继续找下一个区间
        }

        if(ph->next == nullptr) { //查到了末尾,表示无法再分配空间
            return nullptr;
        }

        MNode *ret = (MNode *)(((char *)ph) + nsize + ph->size);
        ret->size = size;
        ret->prev = ph;
        ret->next = ph->next;

        ret->next->prev = ret;
        ret->prev->next = ret;

        ++(*base);
        return ret->data;
    }

    void free(void *ptr) {
        MNode *node = (MNode *)((char *)ptr - sizeof(MNode));
        if(node <= head || node >= tail) { //如果内存数据不在管理范围内, 跳过
            return;
        }
        if(node->prev->next == node->next
            && node->next->prev == node->prev) { // 如果已经释放过, 跳过
            return;
        } 
        node->prev->next = node->next;
        node->next->prev = node->prev;
        --(*base);
    }
private:
    void init() {
        *base = 0;
        head = (MNode *)(base + 1);
        tail = (MNode *)(base + length / sizeof(int)) - 1;

        head->size = 0;
        head->next = tail;
        head->prev = nullptr;

        tail->size = 0;
        tail->prev = head;
        tail->next = nullptr;
    }



private:
    int *base;
    unsigned length;
    MNode *head;
    MNode *tail;
};

以下是测试代码

int buffer[4096];
int main(int argc, char **argv)
{

    MMU mmu(buffer, 4096 * sizeof(int));
    void *memory = mmu.alloc(64);
    std::cout << "新分配地址:" << memory << std::endl;
    void *memory1 = mmu.alloc(16);
    std::cout << "新分配地址:" << memory1 << std::endl;

    mmu.free(memory);
    void *memory2 = mmu.alloc(20);
    void *memory3 = mmu.alloc(16);
    std::cout << "新分配地址:" << memory2 << std::endl;
    std::cout << "新分配地址:" << memory3 << std::endl;
    mmu.free(memory2);
    mmu.free(memory3);
    mmu.free(memory1);
    return 0;
}

没有更多推荐了,返回首页