设想:内存碎片:
由于malloc在内存中连续sbrk申请内存,而释放内存只能从后往前释放。为了达到可以先释放前面申请的内存的效果,每申请一段内存都会有12个字节的内存控制块,控制块的第一个四字节保存前一个申请内存的起始地址,第二个四字节保存当前内存块的标识位,是有效还是无效。第三个四字节记录当前内存块的大小字节。
当程序要先free掉前面申请的内存快的时候,只是把标识位置为0,并没有真正的释放掉内存块,当再次需要申请内存且比之前释放的内存块小的时候,就可以利用之前标识位为0的内存块重新分配内存,而再次分配可能剩下很小的空间永远都使用不上,就变成了碎片一样使内存可用面积越来越小。
include <stdio.h>
include <unistd.h>
include <stdbool.h>
//内存控制块
typedef struct mem_control_block{
bool free; //自由标识
struct men_control_block* prev; //前块指针
size_t size; //本快大小
} MCB;
MCB g_top = NULL ; // 栈顶指针,最后分配
void * my_malloc(size_t size){
MCB* mcb;
for(mcb = g_top;mcb;mcb = mcb->prev){ //首次分配直接跳出,第二次分配会一直找
//到最左mcb->prev = NULL;再跳出,此时mcb一定为NULL
if(mcb->free && mcb->size >= size)
break;
}
if(! mcb){
mcb = sbrk(sizeof(MCB)+size);
if(mcb == (void*)-1)
return NULL;
mcb->prev = g_top;
mcb->size = size;
g_top = mcb;
}
mcb->free = false;
return mcb+1;
}
//free底层实现
void my_free(void* ptr){
if(!ptr)
return;
MCB* mcb = (MCB* )ptr - 1;
mcb->free = true;
for(mcb = g_top; mcb->prev; mcb = mcb->prev)
if(!mcb->free)
break;
if(mcb->free){
g_top = mcb->prev;
brk(mcb);
}
else{
g_top = mcb;
brk((void* )mcb + sizeof(mcb) + mcb->size);
}
}
网友评论