Three Pitfalls To Avoid When Using Dynamically Allocated Memory

February 21st, 2010 by Kevin | Posted under programming.

While using programming languages which do not provide garbage collection, it is left to the programmer to be careful with his usage of  dynamically allocated memory. Improper usage of dynamic memory often leads to subtle bugs which are quite difficult and time consuming to track and resolve.

Following are three pitfalls to avoid while using dynamically allocated memory.

1) Memory Leaks

Dynamic memory is memory allocated and deallocated by the programmer as per usage. Memory leaks arise when we have allocated memory dynamically but have failed to free it. Memory leaks can have a significant impact on the application in situations such as:

  • where the program run for an extended time and consumes additional memory over time, such as background tasks on servers, but especially in embedded devices which may be left running for many years
  • where new memory is allocated frequently, such as when rendering the frames of a computer game or animated video
  • where the program is able to request memory—such as shared memory—that is not released, even when the program terminates
  • where the leak occurs within the operating system
  • where the leak is the responsibility of a system device driver
  • where memory is very limited, such as in an embedded system or portable device

An example:

char * myString = malloc(sizeof(char)*STRING_BUFFER_SIZE); //memory allocated but not freed
if(count > 10)
{
   return count;   //causes a memory leak because myString has not been freed
}
free(myString);
return count;

Avoid pitfall by:

  • Using garbage collection
  • Using reference counting for allocation/deallocation
  • Using static analysis tools such as splint

2) Trying to free already freed memory

Memory which has been dynamically allocated needs to be freed to avoid memory leaks. But for every memory allocation there should be a corresponding deallocation. Trying to free memory more than once can cause serious failure of your application.

An example:

char * myString = malloc(sizeof(char)*STRING_BUFFER_SIZE);
free(myString);
free(myString);   //this causes undefined behaviour. Segmentation fault, crash

Avoid pitfall by:

  • Using reference counting for allocation/deallocation
  • Using static analysis tools such as splint

3) Buffer overrun

Buffer overrun is an anomaly where a process stores data in a buffer outside the memory the programmer set aside for it. The extra data overwrites adjacent memory, which may contain other data, including program variables and program flow control data. This may result in erratic program behavior, including memory access errors, incorrect results, program termination (a crash), or a breach of system security.

An example:

char * myString = malloc(sizeof(char)*STRING_BUFFER_SIZE);
strcpy(myString, string); //Buffer overrun if the size of "string" is greater than STRING_BUFFER_SIZE

Avoid pitfall by:

  • Bounds checking. e.g: Using strncpy() instead of strcpy() to restrict length of copied data.
  • Using static analysis tools such as splint

It is quite difficult to detect and resolve these pitfalls during the program execution. Pitfalls like these can be detected early in the programming phase by conducting a thorough review of the source code. Those which are missed can be further detected and resolved using a good static code analysis tool.

 

Related Posts:

Tags:

Do you have any comments on Three Pitfalls To Avoid When Using Dynamically Allocated Memory ?

Spam protection by WP Captcha-Free