c memory management

part of c programming


  • stack memory is automatically (pre-)allocated memory of your process, used with variable declaration
  • with local variables, it is bound to the scope of the function, and can be used by callees, but when the function ends, the memory is freed
  • it can therefore not be returned from the function that declared it


  • heap memory is additional memory for your process
  • think of allocating heap memory as requesting an access token for using reserved storage in a database
  • the request can fail because there is not enough space or some other reasons
  • only automatically deallocated when the process ends


  • it might be helpful to think in terms of ownership for allocated memory
  • the current owner is the function that is responsible for eventual deallocation
  • ownership can be given, received and lend

memory leaks

  • continuously allocating new space and not freeing it when it is not needed anymore is called a memory leak
  • the available memory space will eventually be filled, preventing new memory from being allocated
  • it prevents programs from running for an indefinite amount of time
  • tools like valgrind can help to trace and find memory leaks

null pointers

  • a pointer is a variable that stores a memory address
  • a null pointer can usually be created by setting a pointer to zero
  • with what bits exactly a null pointer is represented by the compiler is not necessarily specified
  • trying to free a null pointer is usually allowed, but trying to dereference such a pointer leads to an error

double free and corruption

  • calling free on a pointer whose address has previously been freed is an error because there is nothing to free anymore at that address
  • memory corruption can occur when the program haphazardly wrote into the memory outside of the allocated range. this can mess up management structures of the allocator and is a common attack area for security exploits

life time

  • the c compiler has no indication of when memory is not needed anymore. how long a memory area is needed may depend on various application conditions. references to memory areas can be passed between and persist between routine calls. memory stays allocated even if no variable has a reference to it
  • at allocation, decide when the memory is going to be freed. in the successful execution flow as well as when errors occur

freeing all memory allocations up to point

  • when multiple memory areas are allocated and errors occur inbetween, the memory allocated up to point might have to be freed
  • this can be achieved by tracking allocated addresses locally


  • this example uses sph-sc-lib memreg

    • sph-sc-lib also contains a version for multiple named registers and a heap allocated register that can be passed between function calls
  • memreg_init(4) creates an address register on the stack for at most four pointers
  • memreg_register is the variable and memreg_index is the current index
  • memreg_add(address) adds a pointer to the register
  • memreg_free frees all pointers added so far
#include "sph/memreg.c"
int main() {
  int* data_a = malloc(12 * sizeof(int));
  if(!data_a) goto exit;  // have to free nothing
  // more code ...
  char* data_b = malloc(20 * sizeof(char));
  if(!data_b) goto exit;  // have to free "data_a"
  // ...
  if (is_error) goto exit;  // have to free "data_a" and "data_b"
  // ...