LCC编译器的源程序分析(68)内存分配链表

来源:互联网 发布:善游网络 编辑:程序博客网 时间:2024/05/16 12:34
LCC采用大块内存的方法,那它分配内存也是比较特殊的,它的源程序如下:
#001 //大块内存结构。
#002 struct block
#003 {
#004     struct block *next; //后继块指针。
#005     char *limit; //尾位置
#006     char *avail; //可用的开始位置.
#007 };
#008 
#009 //共用最大的类型.
#010 union align
#011 {
#012     long l;
#013     char *p;
#014     double d;
#015     int (*f)(void);
#016 };
#017 
#018 //
#019 union header
#020 {
#021     struct block b;
#022     union align a;
#023 };
#024 
#025 #ifdef PURIFY
#026 union header *arena[3];
#027 
#028 void *allocate(unsigned long n, unsigned a) {
#029     union header *new = malloc(sizeof *new + n);
#030 
#031     assert(a < NELEMS(arena));
#032     if (new == NULL) {
#033          error("insufficient memory/n");
#034          exit(1);
#035     }
#036     new->b.next = (void *)arena[a];
#037     arena[a] = new;
#038     return new + 1;
#039 }
#040 
#041 void deallocate(unsigned a) {
#042     union header *p, *q;
#043 
#044     assert(a < NELEMS(arena));
#045     for (p = arena[a]; p; p = q) {
#046          q = (void *)p->b.next;
#047          free(p);
#048     }
#049     arena[a] = NULL;
#050 }
#051 
#052 void *newarray(unsigned long m, unsigned long n, unsigned a) {
#053     return allocate(m*n, a);
#054 }
#055 #else
#056 
#057 //三大块内存开始头.
#058 static struct block first[] = {
#059     { NULL }, { NULL }, { NULL }
#060 };
#061 
#062 //三大块内存的尾指针.
#063 static struct block *arena[] = { &first[0], &first[1], &first[2] };
#064 
#065 //空闲块的内存头指针.
#066 static struct block *freeblocks;
#067 
#068 //分配n个字节在a区域里.
#069 void *allocate(unsigned long n, unsigned a)
#070 {
#071     struct block *ap;
#072 
#073     assert(a < NELEMS(arena));
#074     assert(n > 0);
#075 
#076     //获取尾块指针。
#077     ap = arena[a];
#078 
#079     //分配需要使用的内存和内存头。
#080     n = roundup(n, sizeof (union align));
#081 
#082     //空闲内存是否大于需要分配的。
#083     while (n > (unsigned long)(ap->limit - ap->avail))
#084     {
#085          //如果有空闲块在列表里。
#086          if ((ap->next = freeblocks) != NULL)
#087          {
#088                //取得已经分配过的大块空闲内存。
#089                freeblocks = freeblocks->next;
#090                ap = ap->next;
#091          }
#092          else
#093          {
#094                //没有大块内存,开始分配大块内存。
#095                unsigned m = sizeof (union header) + n + roundup(10*1024, sizeof (union align));
#096               
#097                //内存真实开始地址.
#098                ap->next = (block*)malloc(m);
#099 
#100                //指向尾指针.
#101                ap = ap->next;
#102               
#103                //分配内存是否出错.
#104                if (ap == NULL)
#105                {
#106                     error("insufficient memory/n");
#107                     exit(1);
#108                }
#109 
#110                //内存块尾地址.
#111                ap->limit = (char *)ap + m;
#112          }
#113 
#114          //实际上可以使用内存开始位置.
#115          ap->avail = (char *)((union header *)ap + 1);
#116 
#117          //下一块内存为空.
#118          ap->next = NULL;
#119          arena[a] = ap;
#120     }
#121 
#122     //移动大块内存的空闲开始位置,n是需要分配的内存.
#123     ap->avail += n;
#124 
#125     //返回分配的内存地址开始位置.
#126     return ap->avail - n;
#127 }
 
 

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1759392


原创粉丝点击