Last modified on 26 December 2013, at 12:39

Memory Management/Manual Memory Management

In every application, you must allocate new storage before you can use it, and then you must return all such storage to the operating system when you are finished. While some languages handle all of this for you, lower-level languages like C or C++ sometimes require more effort by the programmer to manage memory. There are several ways to do this: implicit and explicit.

Implicit memory allocation is memory that is allocated, typically on the system stack, by the compiler. This occurs when you create a new variable:

void my_func(void) {
  int x;
  char y;
  int z[25];
  ...
}

Here, space is allocated on the system stack for the variables x, y and z when the function is called, and the space is reclaimed automatically when the function exits.

Explicit memory allocation occurs through pointers, and calls to the memory management functions:

#include <stdlib.h>
void my_func(void) {
  int * z;
  z = (int *)malloc(25);
  ...
}

Here, we still have variable z which is still being used as an array of 25 integers. However, this storage is not automatically reclaimed when the function exits. This has the added benefit that an array created this way can be returned from the function:

RIGHT WRONG
int *my_func(void) {
  int * x;
  x = (int *) malloc(25);
  return x;
}
int *my_func(void) {
  int x[25];
  return x;
}

Why is one way right, and the other is wrong? The answer is scope: In the left example, the array is created on the heap, and the memory is not reclaimed after the function exits. This means that the memory can still be used even after the function returns. In the example on the right, however, the memory is allocated on the stack and disappears when the function exits.

There are also many places where memory needs to be created in a size which is not known at compile-time. Consider a web browser that needs to allocate enough storage to store the downloaded HTML text of a webpage. Since webpages can be all different sizes, we can't possibly know the sizes of them all when we compile, we must allocate the storage at runtime with malloc or an equivalent.

Memory that is allocated on the stack and is fixed in size and scope is called static. Memory that uses malloc to be allocated at run time is called dynamic.

Freeing Dynamic MemoryEdit

When you allocate memory from the heap using malloc or something similar, you obtain a pointer to allocated memory from the system. When you are done with it, you must free the memory, to return it back to the system. Failure to return all the memory that you allocate is called a memory leak. In C, you can free memory using the free() function.

Problems with Memory ManagementEdit

When you allocate memory, you must always be careful to release your allocated memory back to the system. Herein is the problem: if your system is complicated and needs to allocate many small chunks of memory, you need to be certain to free all those individual little chunks as well. This can be all the more difficult if you are in a dynamic situation where memory is being allocated and deallocated continuously, and memory chunks must stay available for random lengths of time.

To overcome these complications automatic memory manager systems, such as garbage collectors, can be employed to try to automate the memory allocations and deallocations.