Explanation on K&R 8.7 A Storage Allocator

原文链接: http://www.cnblogs.com/sirkay777/archive/2009/03/04/1403374.html

Anyone has a basic knowledge of C can use malloc(), but under the cover what really happens? Well, K&R give us a simple version of a storage allocator. Simple as it is, it is still very hard for the beginners to understand. The free() function is especially confusing, what’s on earth the author’s talking about? OK, fellow me.

 1  /*  free:  put block ap in free list  */
 2      void  free( void   * ap)
 3     {
 4         Header  * bp,  * p;
 5 
 6         bp  =  (Header  * )ap  -   1 ;     /*  point to  block header  */
 7          for  (p  =  freep;  ! (bp  >  p  &&  bp  <  p -> s.ptr); p  =  p -> s.ptr)
 8               if  (p  >=  p -> s.ptr  &&  (bp  >  p  ||  bp  <  p -> s.ptr))
 9                   break ;   /*  freed block at start or end of arena  */
10 
11          if  (bp  +  bp -> size  ==  p -> s.ptr) {     /*  join to upper nbr  */
12             bp -> s.size  +=  p -> s.ptr -> s.size;
13             bp -> s.ptr  =  p -> s.ptr -> s.ptr;
14         }  else
15             bp -> s.ptr  =  p -> s.ptr;
16          if  (p  +  p -> size  ==  bp) {             /*  join to lower nbr  */
17             p -> s.size  +=  bp -> s.size;
18             p -> s.ptr  =  bp -> s.ptr;  // unnecessary maybe?
19         }  else
20             p -> s.ptr  =  bp;
21         freep  =  p;
22     }

 

First, we have bp point to the header of the block we want to put in the free list. Then, we have a working pointer initialized to freep. Because the free list is a singly circularly linked list, we can loop around to find a p where bp is between p and pnext(that is p->s.ptr) in the free list if we assume bp is already in the list(It is important to view the linked list as a circle). How can we describe this condition in C? bp, p and pnext all have a address in the physical memory(view them as linear this time). These addresses are comparable. Normally pnext is greater than p, then we can say p

Now we have bp in the middle of p and pnext in the circularly linked list. The remaining works are keeping the pointers pointing to the right things and the sizes correct. If bp is adjacent to either neighbor, the adjacent blocks are combined. (IMPORTANT!! View the list as circle now, regardless of their physical position, their relative position in the circularyly linked list is fixed, with p be the first, and bp be the midlle one and pnext comes last) If bp is adjacent to pnext, then bp is combined with pnext, pnext vanishes, bp get a new size, bp->s.adr has to point to pnext->s.adr. if bp is not adjacent to pnext, then bp->s.adr has to point to pnext, because pnext comes after bp in the new list. Similarly, if bp is adjacent to p, bp vanishs, and pointers remain the same, p gets a new size. If not, bp->s.adr has to point to bp. Well, All finished.

In summary, the two kinds of view we use here is very important. View the list as linear when we compare the address. View the list as circular when fix the pointers. The observation which allow us to apply general operation on the list is also very important, that is to find a p where bp is between p and pnext(that is p->s.ptr), we can always find such a p, because bp must be anywhere in the memory.

转载于:https://www.cnblogs.com/sirkay777/archive/2009/03/04/1403374.html

你可能感兴趣的:(Explanation on K&R 8.7 A Storage Allocator)