【转载】malloc内存分配与free内存释放的原理

原文链接:http://www.cnblogs.com/zhehan54/p/4749206.html

原文:http://www.cnblogs.com/huhuuu/p/3456662.html

前段时间一直想看malloc的原理,在搜了好几篇malloc源码后遂放弃,晦涩难懂。

  后来室友买了本深入理解计算机系统的书,原来上面有讲malloc的原理,遂看了,先明白理论,在看代码就理解比较快了= =

  1.问题的引入:

   为什么要使用malloc,主要是因为在代码中,为了节约内存,很多数据都是动态生成的,所以会用malloc,对应于C++中的new,底层还是调用malloc.

  2.碎片的问题:

   会有内部碎片与外部碎片的问题,内部碎片难以消除(因为字对齐之类的问题),而外部碎片是可以消除的(如果不消除的话,外部的内存块越来越小,虽然数量多了,但是利用率会急剧下降!)

  3.需要解决的问题:

  

  4.隐式的空闲链表:

  一个简单的堆块,这里只有头部,下面为了优化,还会使用尾部。

  

  隐式的空闲链表:

  

  这样就把用链表的方法把堆空间给联系起来了。特点明显,实现简单,但分配时查询空堆块是线性时间的。

  5.放置以分配的块:

    1)、首次适配:从链表开始寻找适合的空堆块,直到找到为止

    2)、下一次适配:从上一次的分配点开始找,直到找到适合的空堆块为止

    3)、最佳适配:查询整个链表,找到最合适(浪费最小)的空堆块

  6.分割空闲块:

    当前的分配的空堆块比所需要的空间大很多的时候,如果不分割,就会照成内部碎片过大,利用率下降。

    当需要3个字节的空间时,首次适配找到了满足条件的第二个堆块,但堆块过大,所以分割成两个16字节的堆块。

    

  7.获取额外的堆存储器:

   当链表中不能满足申请要求的堆块空间的时候,1)通过合并相邻的堆块空间,形成单个尽量大的堆块空间 2)实在没有其他办法了,分配器通过sbrk函数向内核申请格外的堆空间,分配器将堆空间插入到链表中,然后提供给申请空间的块。

  8.合并

  

  如果,在如上的情况下,合并两个块,由于当前块不知道上一个块的情况,它要通过遍历整个链表才能知道上一个堆块的空间是否为空,这样将花费线性的时间来合并与当前相邻的空闲堆块。有个类似双向链表的方法(不过不是真正的双向链表,只是可以加一个信息量,直接就可以知道上一个堆块的情况)

  

  上一个堆块的情况就容易知道了,下面有四种情况:

  

  

  这样,堆块合并的问题就解决了。

转载于:https://www.cnblogs.com/zhehan54/p/4749206.html

展开阅读全文
博主设置当前文章不允许评论。

malloc()内存释放问题

06-23

代码末尾对malloc()分配的内存内存进行释放,但加上这段代码后编译会出错,不释放反而可以。不说说凡是有malloc()都要free()吗?rnrn[code=c]#includern#includern#includernrn#define TSIZE 45rnrnstruct filmrnrn char title[TSIZE];rn int rating;rn struct film *next; /*指向链表的下一个结构*/rn;rnrnint main(void)rnrnrn struct film * head = NULL;rn struct film * current, * prev;rn char input[TSIZE];rnrn /*收集并存储信息*/rn puts("enter the first movie title:");rn while (gets(input) != NULL && input[0] != '\0')rn rn current = (struct film *)malloc(sizeof(struct film));rn if (head == NULL) /*第一个结构*/rn rn head = current; rn rn else /*后续结构*/rn rn prev->next = current; rn rn current->next = NULL;rn strcpy(current->title, input);rn puts("enter the movie rating(0-10)");rn scanf("%d", &current->rating);rn while (getchar() != '\n')rn rn continue;rn rn puts("enter the next movie title(enter empty line to quit):");rn prev = current;rn rnrn /*给出电影列表*/rn if (head == NULL)rn rn puts("no date entered!");rn rn elsern rn printf("here is the movie list:");rn rn current = head;rn while (current != NULL)rn rn printf("Movie: %s rating: %d", current->title, current->rating);rn current = current->next;rn rnrn /*释放分配的内存*/rn current = head;rn while (current != NULL)rn rn free(current);rn current = current->next;rn rn printf("Bye!");rnrn return 0;rn[/code] 论坛

mallocfree 的问题

08-18

本段代码是把文件读入到内存后再查询,查询后然后释放分配的内存空间,而这时如果使用 malloc() 给分配内存空间,rn调用 freeAll() 使用 free() 进行释放时就会报错,而使用 calloc()进行分配时,再使用调用 freeAll() 使用 free() 进行释放rn是正常的,不知道这是为什么,请各位帮忙,谢谢。rn[code=c]rnrn// 这儿最大的问题是 使用了 malloc() 分配的内存,在使用 free() 进行回收时,会报错。rn//而使用 calloc() 进行分配后就不会出报错,不知道是什么原因。 rnrn#define _CRT_SECURE_NO_WARNINGSrn#includern#includern#includern#includern#includernrnstruct infosrnrn char path[256]; //文件名 rnrn char findstr[256]; //要查询的字符串rn int id; //线程idrnrn char **g_pp; //把文件的内容载入这个地址rn int length; //文件的行数rnmyinfo[1] = 0 ; //1:个结构体保存1个文件的信息 rnrnrnrnvoid runthreadinit(void *p)rnrn struct infos *pinfo = p;rn printf("初始化线程 %d 开始执行......\n", pinfo->id);rn FILE *pf = fopen(pinfo->path, "r");rn if (pf != NULL) //先要确定有多少行,然后才能给分配内存rn rn int k = 0;rn while (!feof(pf))rn rn char str[256];rn fgets(str, 256, pf);rn k++;rn rn pinfo->length = k;rn //下面要把文件装到内存中,所以要让文件回到文件开头rn rewind(pf); //或用 fseek(pf,0,SEEK_SET);rn //分配内存地址rn pinfo->g_pp = malloc(sizeof(char *)*pinfo->length);rn memset(pinfo->g_pp, '\0', sizeof(char *)*pinfo->length);rn if (!pinfo->g_pp)rn rn printf("申请内存失败!\n");rn return;rn rn //calloc();不需要再进行初始化rn //pinfo->g_pp = calloc(pinfo->length, sizeof(char *));rnrn for (int i = 0; i < pinfo->length; i++)rn rn char str[1024] = 0 ;rn fgets(str, 1024, pf);rn int length = strlen(str);rn pinfo->g_pp[i] = malloc(sizeof(char)*length);rn memset(pinfo->g_pp[i], '\0', sizeof(char)*length + 1);rn //pinfo->g_pp[i] = calloc(length + 1, sizeof(char));rn if (pinfo->g_pp[i] != NULL)rn rn if (pinfo->g_pp[i])rn rn strcpy(pinfo->g_pp[i], str);rn rn rn rn rnrn fclose(pf);rn printf("初始化线程 %d 执行结束......\n", pinfo->id);rnrnrnvoid runthreadsearch(void *p)rnrn struct infos *pinfo = p;rnrn printf("线程 %d 开始查询。\n", pinfo->id);rn for (int i = 0; i < pinfo->length; i++)rn rn if (pinfo->g_pp[i])rn rn char *res = strstr(pinfo->g_pp[i], pinfo->findstr);rn if (res)rn rnrn printf("线程:%d 查询到 %s\n", pinfo->id, pinfo->g_pp[i]);rn //Sleep(2000);rn rn rn rn Sleep(2000);rn printf("线程 %d 结束查询。\n", pinfo->id);rnrnrnvoid freeAll(struct infos *pinfo)rnrn printf("freeall");rn for (int i = 0; i < pinfo->length; i++)rn rn free(pinfo->g_pp[i]); //释放指针数组每一个指针指向的内存。rn rn free(pinfo->g_pp);rnrnrnrnrnvoid main()rnrn sprintf(myinfo[0].findstr, "李");rn myinfo[0].id = 1; rn sprintf(myinfo[0].path, "%s", "e:\\qq1.txt");rnrn HANDLE phd1 = _beginthread(runthreadinit, 0, &myinfo[0]);rn //查询前需要等待初始化线程把数据读入到内存中。rn WaitForSingleObject(phd1, INFINITE);rnrn HANDLE phd2 = _beginthread(runthreadsearch, 0, &myinfo[0]);rn WaitForSingleObject(phd2, INFINITE);rnrn system("pause");rnrn //用 malloc() 分配内存时,使用free() 进行释放时就会出错,而用 calloc()进行分配时,rn //使用free()进行释放就不会出错,不知道代码哪里出了问题。rn freeAll(&myinfo[0]); rnrnrn system("pause");rn[/code] 论坛

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