北邮22信通一枚~
跟随课程进度每周更新数据结构与算法的代码和文章
持续关注作者 解锁更多邮苑信通专属代码~
获取更多文章 请访问专栏:
*****声明*****
本代码由官方提供,不是作者的算法。
本代码仅供研究学习使用,请不要用于其他用途。
有问题的友友也可以在评论区留言,我们可以一起讨论。
本代码在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;
}