存储管理

       今天我们看一下lcc的存储管理,在我们写的一些复杂的程序中,都需要用到动态内存的分配,即使用malloc,但我们都知道使用malloc就需要显式的使用free来释放掉。问题是有很多程序员会忘记释放空间,造成内存泄漏。

       lcc在管理内存的思想是统一释放,这主要是来自于我们常遇到的窗口,就是在你关闭窗口时,所分配的按钮,滚动条等都释放了。

       lcc主要是使用了分配区,释放空间的大小也是这个分配区,所以生命周期相似的对象就会统一释放掉。而每一个分配区由一组内存块组成链表,每一个内存块都有一个结构体来指定。

       首先是这个头部结构体的表示:

       struct block

       {

                   struct block *next;

                   char *limit;

                   char *avail;

           };     

       limit是指定内存块内地址的最大值,avail是指定所能分配的地址的最小值,也就是在数据块中大于avail的地址都已经分配出去了。所能用的地址大小是limit - avail.

       在这里我们用到一个数据结构是:

        union align

        {

                 long l;

                 char *p;

                 double d;

                 void (*f)(void);

        };

        这个共用体的主要作用是使所分配的数据在地址空间上是对齐的,联合里给出了宿主机的最小对齐字节数。

        同理:

        union header

        {

                struct block b;

                union align a;

        };

        我想不用说你大概也知道它的作用来吧,对,就是为了ap->avail指向的地址是对齐的。

        下面是数据结构的初始化:

         struct block

                    first[] = { {NULL}, {NULL}, {NULL} };

                    *arena = {  &first[0], &first[1], &first[2]  };

 

         下面主要是分配空间的细节:

          ap = arena[a];

          首先得到要分配的分配区的指针,其实这个指针是指向分配区中能分配的内存块,其他的是已经被分配完的。

          n = roundup(n ,  sizeof(union align));

          roundup宏返回的是离n最近的sizeof(union align)倍数的值,其实它就是为了字节对齐。

          if (ap->avail + n > ap->limit)

          {

                     if((ap->next = freeblocks) != NULL)

                     {

                               freeblocks = freeblocks->next;

                               ap = ap->next;

                     }

                    // 我想你应该知道freeblocks指针的作用吧,恩,它就是指向那些已经释放来空间的头指针

                    else

                     {

                               unsinged m = sizeof(union header) + n + 10 * 1024;

                               ap->next = malloc(m);

                               ap = ap->next;

                               if(ap == NULL)

                              {

                                       exit(1);

                              }

                              ap->limit  = (char *)ap + m;

                     }

 

                     ap->avail = (char *)((union head *)ap + 1);

                     arena[a] = ap;

          }

 

          ap->avail += n;

          return ap->avail -  n;

 

     这里有一个技巧是:

     假设分配形式是:   struct T *p;

                                     p = allocate(sizeof *p,  a);

     我们并没有使用    p = allocate(sizeof T,    a);

     因为后者只有在p确实是struct T指针时才是正确的,否则就会产生错误,而前者则不存在这样的问题.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值