2016-06-09 57 views
1

为函数malloc()的代码的低于困惑K&R执行以K & R段8.7的malloc

void *malloc(unsigned nbytes) { 
    Header *p, *prevp; 
    Header *moreroce(unsigned); 
    unsigned nunits; 

    nunits = (nbytes+sizeof(Header)-1)/sizeof(header) + 1; 
    if ((prevp = freep) == NULL) { /* no free list yet */ 
     base.s.ptr = freeptr = prevptr = &base; 
     base.s.size = 0; 
    } 
    for (p = prevp->s.ptr; ; prevp = p, p = p->s.ptr) { 
     if (p->s.size >= nunits) { /* big enough */ 
      if (p->s.size == nunits) { /* exactly */ 
       prevp->s.ptr = p->s.ptr; 
      } else { /* allocate tail end */ 
       p->s.size -= nunits; 
       p += p->s.size; 
       p->s.size = nunits; 
      } 
      freep = prevp; 
      return (void *)(p+1); 
     } 
     if (p == freep) /* wrapped around free list */ 
      if ((p = morecore(nunits)) == NULL) 
       return NULL; /* none left */ 
    } 
} 

我主要是由“分配尾端”部分相混淆。根据代码,我们首先从p-> s.size中减去2,将p前进3,在该地址记录分配的大小,并返回(void *)(p + 1)。

设p'表示自增后的p,*表示自由空间。上述操作后,内存应该是这样的:

P * * P” *

实际上我们分配了2个单位的内存,但对于p剩余的可用空间应该是2,而不是3,因为一个单元被分配的尾端的头部信息占用。

所以我觉得行

p->s.size -= nunits; 

p->s.size -= nunits + 1; 

代替我错过了什么?

回答

2

答案是在这条线

nunits = (nbytes+sizeof(Header)-1)/sizeof(header) + 1; 

这条线需要请求nbytes的字节数,增加sizeof(Header)-1围捕,通过sizeof(header)分得到的持有nbytes需要的单位数。最后,它增加1以腾出头部空间。因此,之后的所有代码都假定您为nbytes(如果需要,加上填充)和标题保留空间。

+0

谢谢您的澄清!我混淆了这两个变量。但如果是这样,不应该p自增加p-> s.size + 1而是为了得到正确的头部位置? – Loopz

+0

这由返回'p + 1'的'return'语句处理。基本上,代码基于块的概念,其中包括标题,数据和填充。它在开始时调整请求大小,并在末尾调整指针。两者之间的所有内容都使用块指针。 – user3386109

+0

仍然假设p-> s.size = 5。我们有从0到5索引的内存地址。p最初是0,它有1到5的空闲内存。如果nbytes = 2,我认为p应该前进到4并且返回5.但似乎p提前到3,而返回4。 – Loopz