本章学习lcc的内存管理模块,同string处理模块类似,这个模块也可以独立于lcc使用,
实际上这个模块实现的是一个简单的内存池的概念,具体代码如下:
#include "c.h"
/*lcc内存管理的基本单位,以链表组成的block形式存在*/
struct block {
struct block *next;
char *limit;/*从block的起始地址到limit的这段空间表示这个block的总大小*/
char *avail;/*从起始地址到avail是已经分配区域,从avail到limit是可继续分配空间*/
};
union align {
long l;
char *p;
double d;
int (*f)(void);
};
union header {
struct block b;
union align a;
};
#ifdef PURIFY/*主要用于内存问题的debug*/
union header *arena[3];
void *allocate(unsigned long n, unsigned a) {
union header *new = malloc(sizeof *new + n);
assert(a < NELEMS(arena));
if (new == NULL) {
error("insufficient memory\n");
exit(1);
}
new->b.next = (void *)arena[a];
arena[a] = new;
return new + 1;
}
void deallocate(unsigned a) {
union header *p, *q;
assert(a < NELEMS(arena));
for (p = arena[a]; p; p = q) {
q = (void *)p->b.next;
free(p);
}
arena[a] = NULL;
}
void *newarray(unsigned long m, unsigned long n, unsigned a) {
return allocate(m*n, a);
}
#else
static struct block
first[] = { { NULL }, { NULL }, { NULL } },
*arena[] = { &first[0], &first[1], &first[2] };
static struct block *freeblocks;/*指向空闲链表的指针*/
void *allocate(unsigned long n, unsigned a) {
struct block *ap;
assert(a < NELEMS(arena));
assert(n > 0);
ap = arena[a];
//字节对齐
n = roundup(n, sizeof (union align));//sizeof (union align) = 8
while (n > ap->limit - ap->avail) {
if ((ap->next = freeblocks) != NULL) {/*是否有空闲内存*/
freeblocks = freeblocks->next;
ap = ap->next;
} else//malloc new
{
unsigned m = sizeof (union header) + n + roundup(10*1024, sizeof (union align));
ap->next = malloc(m);
ap = ap->next;
if (ap == NULL) {
error("insufficient memory\n");
exit(1);
}
ap->limit = (char *)ap + m;
}
ap->avail = (char *)((union header *)ap + 1);
ap->next = NULL;
arena[a] = ap;
}
ap->avail += n;
return ap->avail - n;/*返回原来的avail*/
}
void *newarray(unsigned long m, unsigned long n, unsigned a) {
return allocate(m*n, a);
}
void deallocate(unsigned a) {
assert(a < NELEMS(arena));
arena[a]->next = freeblocks;//并未真正free,而是加入空闲链表
freeblocks = first[a].next;
first[a].next = NULL;
arena[a] = &first[a];
}
#endif