Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Inside memory management

The choices, tradeoffs, and implementations of dynamic allocation

Return to article


Listing 1. malloc.c
/* Include the sbrk function */ 
#include <unistd.h> 

int has_initialized = 0;
void *managed_memory_start;
void *last_valid_address;

void malloc_init()
{ 
 /* grab the last valid address from the OS */  
 last_valid_address = sbrk(0);     

 /* we don't have any memory to manage yet, so 
  *just set the beginning to be last_valid_address 
  */  
 managed_memory_start = last_valid_address;     

 /* Okay, we're initialized and ready to go */
  has_initialized = 1;   
}

struct mem_control_block { 
 int is_available; 
 int size;
};

void free(void *firstbyte) { 
 struct mem_control_block *mcb;  

 /* Backup from the given pointer to find the 
  * mem_control_block 
  */ 
 mcb = firstbyte - sizeof(struct mem_control_block);   
 /* Mark the block as being available */ 
 mcb->is_available = 1;    
 /* That's It!  We're done. */ 
 return;   
}  

void *malloc(long numbytes) { 
 /* Holds where we are looking in memory */ 
 void *current_location; 

 /* This is the same as current_location, but cast to a 
  * memory_control_block 
  */
 struct mem_control_block *current_location_mcb;  

 /* This is the memory location we will return.  It will 
  * be set to 0 until we find something suitable 
  */  
 void *memory_location;  

 /* Initialize if we haven't already done so */
 if(! has_initialized)  { 
  malloc_init();
 }

 /* The memory we search for has to include the memory 
  * control block, but the user of malloc doesn't need 
  * to know this, so we'll just add it in for them. 
  */
 numbytes = numbytes + sizeof(struct mem_control_block);  

 /* Set memory_location to 0 until we find a suitable 
  * location 
  */
 memory_location = 0;  

 /* Begin searching at the start of managed memory */ 
 current_location = managed_memory_start;  

 /* Keep going until we have searched all allocated space */ 
 while(current_location != last_valid_address)  
 { 
  /* current_location and current_location_mcb point
   * to the same address.  However, current_location_mcb
   * is of the correct type so we can use it as a struct.
   * current_location is a void pointer so we can use it
   * to calculate addresses.
   */
  current_location_mcb = 
   (struct mem_control_block *)current_location;

  if(current_location_mcb->is_available)
  {
   if(current_location_mcb->size >= numbytes)
   {
    /* Woohoo!  We've found an open, 
     * appropriately-size location.  
     */

    /* It is no longer available */
    current_location_mcb->is_available = 0;

    /* We own it */
    memory_location = current_location;

    /* Leave the loop */
    break;
   }
  }

  /* If we made it here, it's because the Current memory 
   * block not suitable, move to the next one 
   */
  current_location = current_location + 
   current_location_mcb->size;
 }

 /* If we still don't have a valid location, we'll 
  * have to ask the operating system for more memory 
  */
 if(! memory_location)
 {
  /* Move the program break numbytes further */
  sbrk(numbytes);

  /* The new memory will be where the last valid 
   * address left off 
   */
  memory_location = last_valid_address;

  /* We'll move the last valid address forward 
   * numbytes 
   */
  last_valid_address = last_valid_address + numbytes;

  /* We need to initialize the mem_control_block */
  current_location_mcb = memory_location;
  current_location_mcb->is_available = 0;
  current_location_mcb->size = numbytes;
 }

 /* Now, no matter what (well, except for error conditions), 
  * memory_location has the address of the memory, including 
  * the mem_control_block 
  */ 

 /* Move the pointer past the mem_control_block */
 memory_location = memory_location + sizeof(struct mem_control_block);

 /* Return the pointer */
 return memory_location;
 }

Return to article