北邮22信通:(9)实验1 题目六:模拟内存管理(搬运官方代码)

北邮22信通一枚~   

跟随课程进度每周更新数据结构与算法的代码和文章 

持续关注作者  解锁更多邮苑信通专属代码~

获取更多文章  请访问专栏:

北邮22信通_青山如墨雨如画的博客-CSDN博客

*****声明*****

本代码由官方提供,不是作者的算法。

本代码仅供研究学习使用,请不要用于其他用途。

有问题的友友也可以在评论区留言,我们可以一起讨论。

本代码在DEVC++中可以运行。

*****声明完毕*****

1.实验要求:

动态内存管理是操作系统的基本功能之一,用于相应用户程序对内存的申请和释放要求;

初始化时,系统只有一块连续的空闲内存;

当不断有用户申请内存时,系统会根据魔种策略选择一块合适的连续内存供用户程序使用;

当用户程序释放内存时,系统将其回收,供以后重新分配,什邡市需要计算该内存块的左右是否也为空闲块,若是,则需要合并变成更大的空闲块;

试设计用于模拟动态内存管理的内存池类。

要求:

实现内存池的初始化;

实现allocate(int size)接口;

实现free(void*p)接口;

实现内存池的析构;

在分配内存空间时可选择不同的内存分配策略:最佳拟合策略、最差拟合策略或最先拟合策略,实现其中指向两种分配策略;

编写测试main()函数对类中的各个接口和各种分配策略进行测试,并实时显示内存池中的占用块和空闲块的变化情况;

考虑如下情况:

初始化内存空间:

定义free used?

分配内存空间:

最佳拟合?最差拟合?最先拟合?

回收内存空间:

找到插入位置?

和当前空闲空间左连续?如何合并?

和当前空闲空间右连续?如何合并?

程序要求:

1.注意异常处理的使用,比如删除空链表时需要抛出异常;

2.注意内存的动态申请和释放,是否存在内存泄漏;

3.优化程序的时间性能;

4.保持良好的编程风格:

代码要简洁;代码段之间按要有空行和缩进;标识符名称用该与其代表的意义一致;函数名之前应该添加注释说明函数的功能;关键代码应说明其功能;

2.代码部分:

#include <iosfwd>
#include <iostream>
using namespace std;

struct Memory{
    unsigned int start;
    unsigned int end;
};

//重载<<运算符
ostream& operator << (ostream& out, Memory& m) //<<运算符重载
{
    out << m.start << "~" << m.end;
    return out;

}
//重载==运算符:精确查找 和 模糊查找
bool operator  ==(Memory& m1, Memory& m2)
{
    if ((m1.start == m2.start)&&(m1.end == m2.end))  
        return true;
    return false;
}

struct MemNode
{
    Memory data;
    MemNode  *prev;
    MemNode  *next;
};

class MemoryPool
{
public:
    MemoryPool();
    MemoryPool(int size);
    MemNode* allocate(int size);         //分配一定大小的内存池
    void free(MemNode *p);                   //删除
    void print();                       //打印内存池情况
    int getFreeLength(){ return freelength;};                   //获取空闲池链表长度
    int getBusyLength(){ return busylength;};                   //获取占用池链表长度
    ~MemoryPool();
private:
    MemNode *free_first;  //空闲池队头
    MemNode *busy_first;  //使用池队头
    int freelength;       //空闲池链表长度
    int busylength;       //占用池链表长度
    MemNode* fittestAllocate(int size);  //最佳拟合策略
    MemNode* firstAllocate(int size);    //最先拟合策略
    MemNode* returnNode(MemNode*);       //创造新的节点及指针作为返回值
    void memoryCollect(MemNode*);        //回收占用内存
    int maxsize;
};

MemoryPool::MemoryPool()
{
    free_first = new MemNode;
    busy_first = new MemNode;
    free_first->next = NULL;
    free_first->prev = NULL;
    busy_first->prev = NULL;
    busy_first->next = NULL;
    freelength = 0;
    busylength = 0;
    maxsize = 0;
}

//初始化空闲池大小为size
MemoryPool::MemoryPool(int size)
{
    //尾插法
    //初始化空闲池头节点      带头结点的双链表
    free_first = new MemNode;
    free_first->prev = NULL;
    free_first->next = new MemNode;
    //初始化空闲池的第一个节点
    free_first->next->data.start = 0;
    free_first->next->data.end = size;
    free_first->next->prev = free_first;
    free_first->next->next = NULL;
    freelength = 1;
    //初始化占用池的头节点
    busy_first = new MemNode;
    busy_first->prev = NULL;
    busy_first->next = NULL;
    busylength = 0;
    maxsize = size;
}

MemoryPool::~MemoryPool()
{
    while (free_first != NULL)
    {
        MemNode *p = free_first;
        free_first = free_first->next;
        delete p;
    }
    while (busy_first != NULL)
    {
        MemNode *p = busy_first;
        busy_first = busy_first->next;
        delete p;
    }
}

MemNode* MemoryPool::allocate(int size) {
    if(size > maxsize){
        throw "It is too large to request such size of memory";
    }
    //MemNode *p = firstAllocate(size);
    MemNode *p = fittestAllocate(size);
    if(p == NULL) {
        cout << "No such size(" << size << ") of memory to be allocated" << endl;
        throw "Program exit when allocating";
    }

    MemNode *q = busy_first;
    while (q->next != NULL)     //将p插入占用链中
    {
        q = q->next;
        if(q->data.start > p->data.start)  
        {
            q->prev->next = p;   //将p插在q前面
            p->prev = q->prev;
            p->next = q;
            q->prev = p;
            busylength++;
            return returnNode(p);
        }
    }
    q->next = p;
    p->prev = q;
    p->next = NULL;
    busylength++;
    return returnNode(p);
}

MemNode* MemoryPool::returnNode(MemNode *ptr)
{
    MemNode *res = new MemNode;
    res->prev = NULL;
    res->next = NULL;
    res->data.start = ptr->data.start;
    res->data.end = ptr->data.end;
    cout <<"**  Returning free memory of "<< res->data << "  **" <<endl;
    return res;
}

MemNode* MemoryPool::firstAllocate(int size) {    //找到第一块符合大小要求的空闲区域
    MemNode *p = free_first;
    while (p->next != NULL){
        p = p->next;
        int remain = p->data.end - p->data.start;
        if (remain == size)
        {
            p->prev->next = p->next;
            if(p->next != NULL)
                p->next->prev = p->prev;
            freelength--;
            return p;
        }
        else if (remain > size)
        {
            MemNode *node = new MemNode;
            node->next = NULL;
            node->prev = NULL;
            node->data.end = p->data.end;
            p->data.end -= size;
            node->data.start = p->data.end;
            return node;
        }
        else
            continue;
    }
    return NULL;
}

MemNode *MemoryPool::fittestAllocate(int size) {   //选择尽量大小相等的空闲区域
    MemNode *p = free_first;
    MemNode *res = NULL;
    int minsize = maxsize;     //某个区域分配完后剩余的内存
    while (p->next != NULL){
        p = p->next;
        int remain = p->data.end - p->data.start;
        if ((remain >= size)&&(remain - size < minsize))
        {
            res = p;       //选中p指针区域作为分配地
            minsize = remain - size;
        }
        else
            continue;
    }
    if(res == NULL)
        return NULL;
    int remain = res->data.end - res->data.start;
    if (remain == size)
    {
        res->prev->next = res->next;
        if(res->next != NULL)
            res->next->prev = res->prev;
        freelength--;
        res->prev = NULL;
        res->next = NULL;
        return res;
    }
    else
    {
        MemNode *node = new MemNode;
        node->next = NULL;
        node->prev = NULL;
        node->data.end = res->data.end;
        res->data.end -= size;
        node->data.start = res->data.end;
        return node;
    }
}

void MemoryPool::print() {
    cout << "Free Memory Pool " << endl;
    MemNode *p = free_first;
    while (p->next != NULL){
        p = p->next;
        cout<< p->data <<" -> ";
    }
    cout<<"NULL"<<endl;
    cout << "Busy Memory Pool " << endl;
    p = busy_first;
    while (p->next != NULL){
        p = p->next;
        cout<< p->data <<" -> ";
    }
    cout<<"NULL"<<endl << endl;
}


void MemoryPool::free(MemNode *p) {
    MemNode *q = busy_first;
    //查找与参数相同的占用内存块并释放
    cout <<"**  Releasing busy memory of "<< p->data << "**" <<endl;
    while (q->next!= NULL){
        q = q->next;
        if(q->data == p->data)
        {
            //将占用内存块从busy链表中删除
            q->prev->next = q->next;
            if (q->next!=NULL){
                q->next->prev = q->prev;
            }
            delete q;
            busylength--;
            memoryCollect(p);  //空闲链中的操作
            return;
        }
    }
    cout <<"Try to free memory use of "<<p->data<<endl;
    throw "Unfortunately, can not find corresponding busy memory";
}

void MemoryPool::memoryCollect(MemNode *ptr) {
    MemNode *p = free_first;
    while (p->next != NULL) //将ptr插入空闲链
    {           
        p = p->next;
        if(p->data.start > ptr->data.start)  //插到p前面
        {
            //将占用内存插回空闲内存池
            //尝试将破碎的内存拼成连续的内存
            int count = 0; //记录左连续与右连续
            //是否左连续,ptr要是在头结点后,不存在左连续
            if ((p->prev != free_first)&&(p->prev->data.end == ptr->data.start))
            {
                p->prev->data.end = ptr->data.end;
                count++;
            }
            //是否右连续
            if (p->data.start == ptr->data.end)
            {
                p->data.start = ptr->data.start;
                count++;
            }
            if (count == 2){
                //左右均连续,合并成一个大的内存块,删除p结点
                p->prev->data.end = p->data.end;
                p->prev->next = p->next;
                if (p->next!=NULL){
                    p->next->prev = p->prev;
                }
                delete p;
                freelength--;
                return;
            }
            else if (count == 1)
            {
                return;
            }
            //既不左连续,也不又连续,空闲链长度加一
            ptr->next = p;
            ptr->prev = p->prev;
            p->prev = ptr;
            freelength++;
            return;
        }
    }
    //是否左连续(到空闲链的结尾了,只要判断是否左连续)并且此时p不能是头结点
    if ((p != free_first)&&(p->data.end == ptr->data.start))
    {
        p->data.end = ptr->data.end;
        return;
    }
    p->next = ptr;
    ptr->prev = p;
    ptr->next = NULL;
    freelength++;
}

int main()
{
    MemoryPool pool = MemoryPool(1000);
    pool.print();
    cout <<"*******************************************"<<endl;
    try {
        MemNode *p = pool.allocate(100);
        pool.print();
        MemNode *r = pool.allocate(500);
        MemNode *q = pool.allocate(100);
        pool.print();

        cout <<"*******************************************"<<endl;
        pool.free(p);
        pool.print();
        pool.allocate(50);
        pool.print();
        pool.free(r);
        pool.print();
        pool.free(q);
        pool.print();

        cout <<"*******************************************"<<endl;
        pool.allocate(2000);

    }
    catch (const char *e) {
        cout << e << endl;
    }
    return 0;
}

3.程序运行结果:

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青山入墨雨如画

你的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值