文档章节

挖一下那些年的东东(模拟内存申请与释放C语言)

August1996_
 August1996_
发布于 2016/05/17 15:20
字数 1095
阅读 13
收藏 0
#include<stdio.h>

#include<stdlib.h>

#include<malloc.h>

#define Type int



typedef struct MBox{

    struct MBox * pre;

    int size;

    struct MBox * next;

    int begin;

    int tag;                        //是否被使用 0是空闲 1是占用

    int end;

}MBox,*pMBox;

//存储内存块的信息



typedef struct Memory{

    int size;

    Type *base;                        //真正的内存

    pMBox first;                    //指向第一个内存块

}Memory,*pMemory;

//一条内存



void fill(pMemory pM,int s,int e,int j){

    for(s;s<=e;s++)

        pM->base[s]=j;

}

//填充是否使用

//s是开始填充位置,e为结束填充位置

//j是0或1

//0是空闲内存,1是已使用内存



int init(pMemory pM){

    int i;

    printf("Well,please enter the memory size:");    

    scanf("%d",&pM->size);

    if(pM->base=(Type *)malloc(sizeof(Type)*(pM->size))){

        pM->first=(pMBox)malloc(sizeof(MBox));

        pM->first->begin=0;

        pM->first->size=pM->size;

        pM->first->next=pM->first->pre=NULL;

        pM->first->end=pM->size-1;

        pM->first->tag=0;

        for(i=0;i<pM->size;i++)

            pM->base[i]=0;

        fill(pM,pM->first->begin,pM->first->end,0);

        return 1;

    }

    else return 0;

}

//初始化内存条信息



int ask_m(pMemory pM,int size){

    int i,flag=0;

    pMBox pMB1,pMB2;

    for(pMB1=pMB2=pM->first;pMB1!=NULL;pMB1=pMB1->next){

        pMB2=pMB1;

        if(pMB2->tag==0 && pMB2->size>=size){

            flag=1;

            break;

        }

    }

    

    if(pMB2->size<size)                            //找不到就返回假,请求失败

        return 0;

    else if(pMB2->size>size){                    //找到比请求所需的大的内存,分割

        pMB1=(pMBox)malloc(sizeof(MBox));

        pMB1->next=pM->first;

        pMB1->pre=NULL;

        pMB1->next->pre=pMB1;

        pM->first=pMB1;



        pMB1->begin=pMB2->begin;

        pMB1->end=pMB1->begin+size-1;

    

        pMB2->begin=pMB1->end+1;

        pMB2->size=pMB2->size-size;



        pMB1->size=size;

        pMB1->tag=1;

        fill(pM,pMB1->begin,pMB1->end,1);

        return 1;

    }

    else if(pMB2->size==size){                    //找到大小刚好合适的直接使用

        pMB2->tag=1;

        fill(pM,pMB2->begin,pMB2->end,1);

        return 1;

    }

}

//请求内存



int free_m(pMemory pM,int MBox_num){

    int i,flag=0;

    pMBox pMB1,pMB2,pMB3;

    if(MBox_num==0)

        return 0;

    for(i=1,pMB1=pM->first;i<MBox_num && pMB1!=NULL;i++,pMB1=pMB1->next);    //索引需要释放的位置



    if(pMB1==NULL || pMB1->tag==0)                    //空闲块,直接返回

        return 0;

    else {

        for(pMB2=pMB1;pMB2!=NULL;pMB3=pMB2,pMB2=pMB2->next){    //寻找第MBox_num要释放的内存块,flag标记是否已经找到可合并内存块

            if(pM->first==pMB1)                                    //如果是第一个,则处理与其他有区别

                pM->first=pMB1->next;                            //因为涉及到内存条的first

            if(pMB2->begin==pMB1->end+1 && pMB2->tag==0){        //寻找是否能找到合并的,条件大家推导下

                pMB2->begin=pMB1->begin;

                pMB2->size=pMB2->size+pMB1->size;

                flag=1;

                break;

            }else if(pMB2->end+1==pMB1->begin && pMB2->tag==0){    //也是寻找可合并的

                if(pM->first==pMB1)

                    pM->first=pMB1->next;

                pMB2->end=pMB1->end;

                pMB2->size=pMB2->size+pMB1->size;

                flag=1;

                break;

            }

        }

        if(pMB2==NULL)    //当pMB2为NULL时,pMB2等于它的上一个备份pMB3

            pMB2=pMB3;

        if(flag==0){    //flag==0就是没有合并的情况

            if(i==1){    //i==1意味着是第1个内存块要被处理,涉及到pM->first

                pMB2->next=pMB1;

                pM->first=pMB1->next;

                pMB1->next->pre=NULL;

                pMB1->pre=pMB2;

                pMB1->next=NULL;

            }else {

                pMB2->next=pMB1;

                pMB1->pre->next=pMB1->next;

                pMB1->next->pre=pMB1->pre;

                pMB1->pre=pMB2;

                pMB1->next=NULL;

            }

        }

        fill(pM,pMB1->begin,pMB1->end,0);

        if(flag==1)

            free(pMB1);

        else pMB1->tag=0;

    }

    Man_m(pM);

}

//释放内存

//MBox_num是释放的占用块的索引



void Travel(pMemory pM){

    int i;

    printf("\nTraveling the mermory!\n");

    for(i=0;i<pM->size;i++)

        printf("%d ",pM->base[i]);

    printf("\n\n");

}

//遍历内存使用情况



void showBox(pMemory pM){

    int i=1;

    pMBox pB=pM->first;

    printf("\nTraveling the MBox!\n");

    while(pB!=NULL){

        printf("*************************  MBox%d:0x%.8x  *****************************\n",i++,pB);

        printf("* pre         size        next        begin       tag         end        *\n");

        printf("* 0x%.8x ",pB->pre);

        printf(" %.10d ",pB->size);

        printf(" 0x%.8x ",pB->next);

        printf(" %.10d ",pB->begin);

        printf(" %.10d ",pB->tag);

        printf(" %.10d *\n",pB->end);

        printf("**************************************************************************\n\n");

        pB=pB->next;

    }

}

//遍历内存块信息



int Man_m(pMemory pM){

    pMBox pMB1,pMB2,pMB3;

    MBox MB;

    int i,j,k;

    for (pMB3=pM->first;pMB3->tag==1 && pMB3!=NULL;pMB3=pMB3->next);    //因为空闲块都在后面

                                                                        //所以找到第一块空的,后面的都是空的了

    if(pMB3==NULL)

        return 0;                                                        //这是找不到占用块的情况



    for(pMB2=pMB3,i=1;pMB2->next!=NULL;i++,pMB2=pMB2->next);            //这是计算一共有多少个空闲块



    if(i==1)

        return 0;

    else {

        for(j=1;j<i;j++){                                                //简单用冒泡排序把小的空闲块排到前面

            pMB1=pMB3;

            pMB2=pMB3->next;

            for(k=1;k<i;k++,pMB1=pMB1->next,pMB2=pMB2->next){

                if(pMB2->size<pMB1->size){

                    MB.size=pMB1->size;

                    MB.begin=pMB1->begin;

                    MB.end=pMB1->end;



                    pMB1->size=pMB2->size;

                    pMB1->begin=pMB2->begin;

                    pMB1->end=pMB2->end;



                    pMB2->size=MB.size;

                    pMB2->begin=MB.begin;

                    pMB2->end=MB.end;

                }

            }

        }

    }

}

//整理空闲块,保持小空闲块在前,大的空闲在后

//易于请求内存时先利用小的,再拆分大的



int main(){

    Memory m;

    init(&m);

    ask_m(&m,2);

    Travel(&m);

    showBox(&m);



    ask_m(&m,4);

    Travel(&m);

    showBox(&m);



    free_m(&m,2);

    Travel(&m);

    showBox(&m);



    ask_m(&m,2);

    Travel(&m);

    showBox(&m);

    return 0;

}

 

© 著作权归作者所有

共有 人打赏支持
August1996_
粉丝 2
博文 51
码字总数 29055
作品 0
湛江
程序员
私信 提问
C语言内存管理讲解

谨记 人生有两条路,一天需要用心走,叫做梦想;一条需要用脚走,叫做现实。心走的太快,会迷路的;脚走的太快,会摔倒的;心走的太慢,现实会苍白;脚走的太慢,梦不会高飞。人生的精彩,是...

长风留言
2017/11/22
0
0
malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符

malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存 对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的...

sobeit
2010/04/21
974
0
C语言开发中的内存检测基本模块

一、前言 在用C语言开发产品时,由于C语言中的指针操作的灵活性,因此在使用指针时也需要特别小心,稍微不严谨就会导致内存问题,如内存未初始化,内存泄露,内存重复释放等。 但是在实际开发...

墙头草
2011/05/26
0
0
《从零开始学Swift》学习笔记(Day 71)——Swift与C/C++混合编程之数据类型映射

原创文章,欢迎转载。转载请注明:关东升的博客 如果引入必要的头文件,在Objective-C语言中可以使用C数据类型。而在Swift语言中是不能直接使用C数据类型,苹果公司为Swift语言提供与C语言相...

tony关东升
2018/06/26
0
0
《从零开始学Swift》学习笔记(Day 71)——Swift与C/C++混合编程之数据类型映射

原创文章,欢迎转载。转载请注明:关东升的博客 如果引入必要的头文件,在Objective-C语言中可以使用C数据类型。而在Swift语言中是不能直接使用C数据类型,苹果公司为Swift语言提供与C语言相...

智捷课堂
2016/03/02
19
0

没有更多内容

加载失败,请刷新页面

加载更多

4.57 MariaDB慢查询日志 4.58 Tomcat_JDK部署 4.59 zrlog安装 4.60 Nginx代理Tomcat

4.57 MariaDB慢查询日志 为什么要配置慢查询日志? 目的是为了帮助我们分析MariaDB的瓶颈点。 如何配置? 1)进入MariaDB里面执行:show variables like 'slow%';show variables li...

Champin
今天
3
0
自动机器学习简述(AutoML)

为什么需要自动机器学习 对于机器学习的新用户而言,使用机器学习算法的一个主要的障碍就是算法的性能受许多的设计决策影响。随着深度学习的流行,工程师需要选择相应的神经网络架构,训练过...

naughty
今天
2
0
Android Studio Unable to resolve dependency for错误的排查

记录一次Android Studio Unable to resolve dependency for错误的排查 Android Studio 3.2.1 错误提示 Unable to resolve dependency for... 原因:在gradle中设置的代理并没有gradle 4.6的版......

Gemini-Lin
今天
0
0
java常用设计模式

设计模式; 一个程序员对设计模式的理解: “不懂”为什么要把很简单的东西搞得那么复杂。后来随着软件开发经验的增加才开始明白我所看到的“复杂”恰恰就是设计模式的精髓所在,我所理解的“...

呵呵哒灬
今天
5
0
Kafka入门

1、Kafka使用背景 在我们大量使用分布式数据库、分布式计算集群的时候,是否会遇到这样的一些问题: 我们想分析下用户行为(pageviews),以便我们设计出更好的广告位 我想对用户的搜索关键词...

watermelon11
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部