Department of Engineering

IT Services

Memory Allocation

Space is automatically set aside for variables when they are defined, but sometimes you don't know beforehand how many variables you'll need or just how long an array might need to be. The malloc command creates space, returning a pointer to this new area. To illustrate its use and dangers, here's a sequence of attempts at writing a string reverser program.

#include <stdio.h>
#include <stdlib.h>
void print_reverse(char *str)
{
int i;
unsigned int len;

len = strlen(str) - 1; /* Why the -1? Because arrays start at 0,
                          so if a string has n chars, the 
                          last char will be at position n-1 
                        */
for (i=len; i>=0; i--)
    putchar(str[i]);
}

int main()
{
char input_str[100] /* why 100? */
  printf("Input a string\n");
  gets(input_str);  /* should check return value */
  printf("String was %s\n", input_str);
  print_reverse(input_str);
}

This works, but is a bit `loose' (suppose the user types more than 100 characters?) and doesn't keep a copy of the reversed string should it be needed later. The next example shows a wrong (but not uncommon) attempt to solve the latter limitation.

#include <stdio.h>
/* WRONG! */
char* make_reverse(char *str)
{
int i, j;
unsigned int len;
char newstr[100];
len = strlen(str) - 1;
j=0;

for (i=len; i>=0; i--;)
    newstr[j] = str[i];
    j++;
/* now return a pointer to this new string */
return newstr;
}

int main()
{
char input_str[100]; /* why 100? */
char *c_ptr;
  printf("Input a string\n");
  gets(input_str);  /* should check return value */
  c_ptr = make_reverse(input_str); 
  printf("String was %s\n", input_str);
  printf("Reversed string is %s\n", c_ptr);  
}

Like many flawed C programs this will work much of the time, especially if it's not part of a bigger program. The problems are that :-

  • The memory allocated for newstr when it was declared as an `automatic' variable in make_reverse isn't permanent - it only lasts as long as make_reverse() takes to execute. However, the array's contents aren't erased, they're just freed for later use, so if you access the array from main you might still get away with it for a while. Making newstr a static will preserve the data but only until it's overwritten by a subsequent call.

  • The newly created array of characters, newstr, isn't terminated with a zero character, `\0', so trying to print the characters out as a string may be disastrous. `Luckily' the memory location that should have been set to zero is likely to be zero anyway.

Let's try again.

/* mallocing.c */
#include <stdio.h>
#include <stdlib.h>
char* make_reverse(char *str)
{
int i;
unsigned int len;
char *ret_str, *c_ptr;
len = strlen(str);

 /* Create enough space for the string AND the final \0.
  */
 ret_str = (char*) malloc(len +1); 
 /*
    Now ret_str points to a `permanent' area of memory.
  */

 /* Point c_ptr to where the final  '\0' goes and put it in */
 c_ptr = ret_str + len;
 *c_ptr = '\0';

 /* now copy characters from str into the newly created space.
    The str pointer will be advanced a char at a time,
    the cptr pointer will be decremented a char at a time. 
  */
 while(*str !=0){ /* while str isn't pointing to the  last '\0' */
   c_ptr--;
   *c_ptr = *str;
   str++; /* increment the pointer so that it points to each
            character in turn. */
 }
 return ret_str;
}

int main()
{
char input_str[100]; /* why 100? */
char *c_ptr;
  printf("Input a string\n");
  gets(input_str);  /* Should check return value */
  c_ptr = make_reverse(input_str); 
  printf("String was %s\n", input_str);
  printf("Reversed string is %s\n", c_ptr);  
}

The malloc'ed space will be preserved until it is explicitly freed (in this case by doing `free(c_ptr)'). Note that the pointer to the malloc'ed space is the only way you have to access that memory: lose it and the memory will be inaccessible. It will only be freed when the program finishes.

malloc is often used to create tree and list structures, since one often doesn't know beforehand how many items will be needed. See section A.4 for an example.