Skip to content
UniCircle
EasyConceptualDynamic memory

malloc vs calloc vs realloc, and what free really does

Question C-MEM-002

Compare malloc, calloc and realloc. What does free do, and what are memory leaks and dangling pointers?

Show the explanation

All three allocate on the heap and return void * (or NULL on failure).

  • `malloc(size)` gives size bytes. The contents are not initialised; they can hold anything.
  • `calloc(count, size)` gives room for count objects and sets every byte to zero. Good implementations also detect overflow in count * size.
  • `realloc(ptr, new_size)` resizes a block. It may grow it where it is, or allocate a new block, copy the old bytes and free the old one. So the address can change.
  • Safe pattern: int *tmp = realloc(p, n * sizeof *p); if (tmp) p = tmp;. Writing p = realloc(p, ...) loses the original block (a leak) when realloc fails and returns NULL.
  • `free(ptr)` hands the block back to the allocator. It does not clear the memory or set your pointer to NULL. free(NULL) is a safe no-op.

Bugs to name in an interview

  • Memory leak: losing the last pointer to a block without freeing it. Long-running programs grow until they fail.
  • Dangling pointer / use-after-free: using a pointer after free. This is undefined behaviour and a common security bug. Setting p = NULL right after free(p) helps.
  • Double free: calling free twice on the same block. Also undefined behaviour.
  • Forgetting to check for NULL after allocating.

Tools: Valgrind or AddressSanitizer (gcc -fsanitize=address -g) report leaks, use-after-free and out-of-bounds writes.

Style note: in C, do not cast the result of malloc (int *p = malloc(n * sizeof *p);). C converts void * automatically, and the cast can hide a missing #include <stdlib.h>. In C++ the cast is required, but there you would use new or containers anyway.

Original UniCircle question. Last reviewed 22 Oct 2026.