top of page

Allocating Memory Dynamically in C

Introduction


Let's say I have an array of size 50 that the user fills through input... but throughout my program, the user adds one element after the other, and eventually that number far exceeds 50.


Or on the flipside, the user uses only a quarter of the 50 elements available in the array. In both of these cases, either there isn't enough memory allocated to our array or memory is being wasted--reserved, but never used during the program.


Wouldn't it be nice to dynamically reserve memory in our array each time the user requests for another element?


This article will tackle dynamic memory allocation in C, a helpful tool for when we don't know how much memory we need at compile-time.


As a side note, my latest posts on pointers may help provide some additional context for this topic, so if you haven't already, give them a read!


Stack vs Heap


So within memory (referring to RAM), there are different "areas" assigned to storing different data. For instance, environment variables are found at a different "location" than local variables, found in the stack.

It turns out the heap and stack exist in really the same location, they just fill in different directions, as indicated by the arrows.


When both areas intersect, there is no memory left and your program crashes. Similarly, the term "stack overflow" is when a program tries to use more memory in the stack than there is.


It turns out that normally allocated memory, through initializing local variables, is stored in the stack, while dynamically allocated memory lives in the heap.


Allocating Memory

In order to allocate memory, we use the function malloc( ):

  • part of stdlib.h

  • takes a number of bytes to allocate as a parameter

    • ex: if I want to allocate enough memory for an int, which uses four bytes, malloc(4) would find four consecutive bytes and reserve them

  • returns a pointer to the memory it allocated OR returns NULL if there wasn't enough memory available


Now, to use the memory allocated by malloc( ), we need to dereference the variable it's stored to, since it is a pointer.


For instance:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	// stores 12 in four bytes of memory allocated in the stack
	int x = 12;

	// px points to the four bytes of memory allocated in the heap
	int *px = malloc(4);
	// dereferences px to store the value 12 within
	*px = 12;
}

If you don't quite know the number of bytes within a data type, it's generally safer to use the sizeof( ) function, which takes the name of a data type as a parameter:

long long *px = malloc(sizeof(long long));

Similarly, dynamic memory allocation works with arrays (and strings):

// allocates memory for an array of 12 doubles on the heap
double *array = malloc(12 * sizeof(double));

// allocates memory for a string of length 12 on the heap
char *string = malloc(12 * sizeof(char));

*This can come in handy as you can keep allocating small pieces of memory throughout the program and using another function realloc( ) to resize arrays.


Freeing Memory and Memory Leaks


One catch with dynamically allocated memory is that, unlike memory allocated on the stack, memory in the heap is not automatically returned to the system for later use once the program is done.


This can result in a memory leak, which means some of your memory is depleted, which can make your computer slower. This can explain why leaving browsers open for extended periods of time can slow down your computer--memory is being allocated but never freed because the program isn't quite "finished."


That's why it's imperative that you use the function free( ) when you're done working with any dynamically allocated memory in order to "unreserve" it.

  • takes the pointer variable that has memory allocated to it as a parameter


// creates and uses memory using malloc
int* x = malloc(sizeof(int));
*x = 2;

// frees memory after processes are done
free(x);

Final Thoughts


So as a rule of thumb:

  • memory reserved by malloc( ) must be accompanied by free( ) once done using it

  • only dynamic memory on the heap (created by malloc( )) should be freed

  • only free( ) a block of memory once to avoid memory leaks


Thanks for reading!

Comments


bottom of page