Previous Page
Next Page

12.3. Resizing and Releasing Memory

When you no longer need a dynamically allocated memory block, you should give it back to the operating system. You can do this by calling the function free( ). Alternatively, you can increase or decrease the size of an allocated memory block by calling the function realloc( ). The prototypes of these functions are as follows:

void free( void * ptr );

The free( ) function releases the dynamically allocated memory block that begins at the address in ptr. A null pointer value for the ptr argument is permitted, and such a call has no effect.

void *realloc( void * ptr, size_t size );

The realloc( ) function releases the memory block addressed by ptr and allocates a new block of size bytes, returning its address. The new block may start at the same address as the old one.

realloc( ) also preserves the contents of the original memory blockup to the size of whichever block is smaller. If the new block doesn't begin where the original one did, then realloc( ) copies the contents to the new memory block. If the new memory block is larger than the original, then the values of the additional bytes are unspecified.

It is permissible to pass a null pointer to realloc( ) as the argument ptr. If you do, then realloc( ) behaves similarly to malloc( ), and reserves a new memory block of the specified size.

The realloc( ) function returns a null pointer if it is unable to allocate a memory block of the size requested. In this case, it does not release the original memory block or alter its contents.

The pointer argument that you pass to either of the functions free( ) and realloc( )if it is not a null pointermust be the starting address of a dynamically allocated memory block that has not yet been freed. In other words, you may pass these functions only a null pointer or a pointer value obtained from a prior call to malloc( ), calloc( ), or realloc( ). If the pointer argument passed to free( ) or realloc( ) has any other value, or if you try to free a memory block that has already been freed, the program's behavior is undefined.

The memory management functions keep internal records of the size of each allocated memory block. This is why the functions free( ) and realloc( ) require only the starting address of the block to be released, and not its size. There is no way to test whether a call to the free( ) function is successful, because it has no return value.

The function getline( ) in Example 12-1 is another variant of the function defined with the same name in Example 9-4. It reads a line of text from standard input and stores it in a dynamically allocated buffer. The maximum length of the line to be stored is one of the function's parameters. The function releases any memory it doesn't need. The return value is a pointer to the line read.

Example 12-1. The getline( ) function
// Read a line of text from stdin into a dynamically allocated buffer.
// Replace the newline character with a string terminator.
// Arguments:    The maximum line length to read.
// Return value: A pointer to the string read, or
//               NULL if end-of-file was read or if an error occurred.

char *getline( unsigned int len_max )
  char *linePtr = malloc( len_max+1 );       // Reserve storage for "worst case."
  if ( linePtr != NULL )
    // Read a line of text and replace the newline characters with
    // a string terminator:
    int c = EOF;
    unsigned int i = 0;
    while ( i < len_max && ( c = getchar( ) ) != '\n' && c != EOF )
      linePtr[i++] = (char)c;
    linePtr[i] = '\0';

    if ( c == EOF && i == 0 )      // If end-of-file before any
    {                              // characters were read,
       free( linePtr );            // release the whole buffer.
       linePtr = NULL;
    else                           // Otherwise, release the unused portion.
       linePtr = realloc( linePtr, i+1 );     // i is the string length.
  return linePtr;

The following code shows how you might call the getline( ) function:

    char *line;
    if (( line = getline(128) ) != NULL )   // If we can read a line,
      /* ...  */                            // process the line,
      free( line );                         // then release the buffer.

Previous Page
Next Page