C语言中malloc函数实现
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
C语⾔中malloc函数实现
该实现使⽤⼤容量的静态数组作为堆,但也可使⽤操作系统调⽤分配堆。
定义了⼀个数据类型Header保存每个存储器块的簿记信息,定义了具有Header类型元素的堆数组,这样就可以很容易地将簿记信息保存在存储器块中。
类型Header包含了3块信息:指向列表的下⼀个块的指针,当前分配空间的长度,后⾯的⾃由空间的长度。
另外,类型Header的定义还使⽤了⼀个union声明和Align数据类型,这是将存储器元素排在合理的字节边界上,根据系统的不同,这有时是需要的,有时是不需要的。
在malloc函数中,当申请空间时,⾄少要分配两个Header元素节点,有什么原因吗?当然有,因为每个空间块都包含两部分:空间头和空间体。
空间头是为维护堆⽽设计的,说到底就是维护已⽤空间链表,为搜索空闲空间和释放已⽤空间服务。
空间体是供⽤户读写的,当malloc函数返回给⽤户⼀个指针时,⽤户就可以设定⾃⼰的规格,⽐如强制转换成int或double类型,接下来就可以按照这种规格进⾏读写了。
需要注意⼀点,空间头是不能被⽤户访问的,它是⽤来维护堆的,不是为⽤户服务的,所以malloc函数返回的指针是指向空间体的,⽽不是指向空间头的,理所当然free函数得到的指针也是指向空间体的。
可是为了释放空间,free函数需要得到该空间的空间头信息,所以实现时需要把指针调整⼀下,改为指向空间头,此情形下,加⼀即可。
另外⼀点,空间头和空间体同为Header类型,⽤union声明再合适不过。
下⾯就是malloc函数和free函数的实现代码:
#define NULL 0
#define MEMSEZE 8096
typedef double Align;
typedef union header
{
struct {
union header* next;
unsigned usedsize;
unsigned freesize;
}s;
Align a;
}header;
static Header mem[MEMSIZE];
static Header* memptr=NULL;
void* malloc(unsigned nbytes)
{
Header *p,*newp;
unsigned nunits;
nunits=(nbytes+sizeof(Header)-1)/sizeof(Header)+1;
if(memptr==NULL)
{
memptr->s.next=memptr=mem;
memptr->edsize=1;
memptr->s.freesize=MEMSIZE-1;
}
for(p=memptr;(p->s.next!=memptr) && (p->s.freesize<nunits);p=p->s.next);
if(p->freesize<nunits) return NULL;
newp=p+p->edsize;
newp->edsize=nunits;
newp->s.freesize=p->s.freesize-nunits;
newp->s.next=p->s.next;
p->s.freesize=0;
p->s.next=newp;
memptr=newp;
return (void*)(newp+1);
}
void free(void* ap)
{
Header *bp,*p,*prev;
bp=(Header*)ap-1;
for(prev=memptr,p=memptr->s.next;
(p!=bp) && (p!=memptr);prev=p,p=p->next);
if(p!=bp) return;
prev->s.freesize+=p->edsize+p->s.freesize;
prev->s.next=p->s.next;
memptr=prev;
}。