Skip to content
UoL CS Notes

Dynamic Memory Allocation, Stack & Heap

COMP281 Lectures

C Memory Management

So far we have seen:

  • Static-duration Variables (Allocated in Main Memory)
  • Automatic-duration Variables (Allocated on the Stack)

There are two issues with these types of variables:

  • The size of the allocation must be compile-time constant.
  • Their persistence cannot be manually controlled.

Dynamic Memory Allocation

Dynamic memory is allocated into the heap which grows in the opposite direction to the stack.

malloc

void *malloc(size_t size);
  • It takes the size of the memory to be allocated,
  • and returns the pointer to the memory that has been allocated.

We can type cast this pointer into the type that we want to put in that memory.

We can use malloc like so:

int *arr;
arr = (int *)malloc(10 * sizeof(int));

We can then use this as an array of integers as this is a pointer to 10 ints worth of space.

calloc

void *calloc(size_t nmemb, size_t size);
  • nmemb - The number of things to store.
  • size - The size of the thing to store.

This function also initialises the memory that is allocated.

  • It also returns a pointer to the memory requested.

We can use it like so:

int *arr;
arr = (int *)calloc(10, sizeof(int));

realloc

Increases or decreases the size of the specified block of memory, reallocates it if needed:

void *realloc(pointer, int new_size);

Not Enough Memory

If there isn’t enough memory available then malloc and calloc will return NULL.

We can handle this like so:

int *arr = (int *)malloc(10 * sizeof(int));
if (arr == NULL) {
	fprintf(stderr, "out of memory!\n");
	exit(1);
}
/* code that uses arr… */

free

We can call free on the pointer to memory to return the memory back to the operating system.

It may be useful to set the pointer to NULL after the memory has been freed as a reminder.

We can use it like so:

int *j;
j = (int *)malloc(2 * sizeof(int));
free (j);

Memory Leaks

Failure to deallocate memory using free elads to a build-up of non-reusable memory.

This wastes memory resources and can lead to allocation failures.

We can use tools such as valgrind to debug memory leaks.

The Stack

Local variables, function arguments and return values are all stored on the stack.

  • Each function call generates a new stack frame.
  • After a function returns, the stack frame disappears, along with ll local variable and function arguments for that invocation.

Each time we call a recursive function, it’s variables and space for it’s return value is stored on the stack. This will grow until the function unwinds.