Chinaunix首页 | 论坛 | 博客
  • 博客访问: 91705
  • 博文数量: 12
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 170
  • 用 户 组: 普通用户
  • 注册时间: 2013-06-19 08:56
文章分类

全部博文(12)

文章存档

2015年(8)

2014年(4)

我的朋友

分类: LINUX

2014-11-28 17:54:25

一 .问题引出
    以下程序执行后占用内存近1G。。。

点击(此处)折叠或打开

  1. int times = 10000;
  2.     int i = 0;
  3.     char *alloc[times];
  4.     for(i = 0; i < times; i++)
  5.     {
  6.         alloc[i] = (char*)malloc(100000);
  7.         memset(alloc[i], 1, 100000);
  8.     }

  9.     //for(i = 0; i < times; i++)
  10.     for(i = 0; i < times - 1; i++)
  11.     {
  12.         free(alloc[i]);
  13.     }
  14.     while(1)
  15.         sleep(10);
  16.     return 0
原因:因为在malloc申请内存的过程中(小于128K,用brk方式分配内存;否则mmap方式),数据段的高地址指针_edata一直在后移(向高地址移动)。但在释放空间的时候,由于高地址处的空间并没有释放,因此导致堆空间并没有被压缩,因此程序占用近1G的空间。如果循环free的语句替换为注释的那条语句,则没有这个问题。
----------------------------------------------------------------------------------------------------------------------------------------------------
下面这个程序也占内存近1G。。。。

点击(此处)折叠或打开

  1. #include <stdlib.h>
  2.     #include <unistd.h>
  3.     #include <stdio.h>
  4.     #include <string.h>
  5.     int main()
  6.     {
  7.         int times = 20000;
  8.         char* small[times];
  9.         char* big[times];
  10.         for(int j=0; j<1; j++)
  11.         {
  12.             for(int i=0; i<times; i++)
  13.             {
  14.                 big[i] = (char*)malloc(50000);
  15.                 memset(big[i], 1, 50000);
  16.                 small[i] = (char*)malloc(1);
  17.                 memset(small[i], 1, 1);
  18.             }
  19.             for(int i=0; i<times; i++)
  20.             {
  21.                 free(small[i]);
  22.                 free(big[i]);
  23.             }
  24.         }
  25.         //char *alloc = (char*)malloc(2000);
  26.         //free(alloc);
  27.         while(1)
  28.         {
  29.           sleep(10);
  30.         }
  31.         return 0;
  32.     }
原因:程序在malloc时会根据申请空间的大小执行不同的分支(fastbin,bins,largebin)。
fastbin:申请空间小于80Bytes时,如上面small数组
bins:申请空间在80Byte~~128K
largebin:申请空间大于128K时,采用mmap方式
同时在free的时候操作也不一样。
对于fastbin来说,free()小空间(如small[i])时直接连接到fastbin list上,同时使用标志位不改,仍为1,以便下次申请时直接拿走(这样效率高)。
对于big[i]的空间来说,先放到unsorted list上缓存,然后根据需要在放到相应的bin上。
因此对于上面的程序,虽然对所有空间都执行了free操作,但是small[i]所占空间的标志位仍为1,而big[i]它试图合并相邻的块,但是和它相邻的块的使用位还是 1 ,所以它不能把相邻的块合并。所以使用的堆无法压缩。

如果在外循环后面再分配 2000 字节然后释放的话,所有内存将全部清空。这是因为在申请 2000 字节的时候,由 malloc 的第二步,程序会先调用 consolidate ,即把所有的 fastbins 清空,同时把相邻的块合并起来,等到所有的 fastbins 清空的时候,所有的块也被合并去来了,然后调用 free2000 字节的时候,这块被将被合并起来 ,成为 topchunk ,并且大小远大于 64k ,所有堆将会收缩,内存归还给系统。



相关参考如下:
1、框架介绍
http://blog.csdn.net/ugg/article/details/4344247
2、源码分析

3、概要
http://blog.163.com/xychenbaihu@yeah/blog/static/132229655201210975312473/
4、FreeBSD-7 内核mallc源码分析(可对比查看)
http://blogimg.chinaunix.net/blog/upfile2/080101160701.pdf
5、内存分配方式介绍
http://blog.csdn.net/ugg/article/details/4344522


阅读(1575) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~