malloc
首先定义一个block链表的头指针,初始化为NULL,另外,我们需要剩余空间至少有 BLOCK_SIZE + 4 才执行分离操作
#define align4(x) (((((x)-1)>>2)<<2)+4)
#define BLOCK_SIZE 12
void *base = NULL;
void *malloc(size_t size)
{
t_block b, last;
size_t s;
s = align4(size);
if(base)
{
//first find a block
last = base;
b = find_block(&last, s);
if(b)
{
//can we split
if((b->size - s) >= (BLOCK_SIZE + 8))
split_block(b, s);
b->free = 0;
}
else
{
//no fitting block, extend the heap
b = extend_heap(last, s);
if(!b)
return NULL;
}
}
else
{
//first time
b = extend_heap(NULL, s);
if(!b)
return NULL;
base = b;
}
return b->data;
}
calloc
自动将分配到的内存空间初始化
void *calloc(size_t numitems, size_t size)
{
size_t *new;
size_t s, i;
new = malloc(numitems * size);
if(new)
{
//因为申请的内存总是4的倍数,所以这里我们以4字节为单位初始化
s = align4(numitems * size) >> 2;
for(i = 0; i < s; ++i)
new[i] = 0;
}
return new;
}
free
先合并相邻的空闲内存块,合并之后,再检查是否还有空闲的相邻内存块,如果有则继续合并,直到最后,该内存块是最大的连续内存块。
void free(void *p)
{
t_block b;
if(valid_addr(p))//地址的有效性验证
{
b = get_block(p);//得到对应的block
b->free = 1;
//如果相邻的上一块内存是空闲的就合并,
//合并之后的上一块还是空闲的就继续合并,直到不能合并为止
while(b->prev && b->prev->free)
{
b = fusion(b->prev);
}
//同理去合并后面的空闲block
while(b->next)
fusion(b);//内部会判断是否空闲
//如果当前block是最后面的那个block,此时可以调整break指针了
if(NULL == b->next)
{
if(b->prev)//当前block前面还有占用的block
b->prev->next = NULL;
else//当前block就是整个heap仅存的
base = NULL;//则重置base
brk(b);//调整break指针到b地址位置
}
//否则不能调整break
}
}