2016-06-09 61 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