Dynamic Memory
Your Desk vs. The Warehouse
When you declare a variable like int x = 5;, it lives on the stack — think of it as your desk. It's fast, tidy, and automatically cleaned up when you leave the room (when the function returns). But your desk is small. You can't fit a million sticky notes on it.
The heap is like a giant warehouse. It has tons of space, but there's a catch: you have to reserve shelves, you have to label them, and you have to put things back when you're done. Forget to clean up? Congratulations, you've got a memory leak.
The Four Functions
C gives you four tools to manage the warehouse:
- malloc — reserve a chunk of memory (uninitialized — could contain garbage)
- calloc — reserve AND zero-initialize memory
- realloc — resize a previously allocated chunk
- free — return memory back to the system
All four live in <stdlib.h>.
Allocating a Single Integer
malloc — Raw Memory
malloc(size) allocates size bytes and returns a pointer to the first byte. The memory is not initialized — it contains whatever garbage was there before. Think of it as renting a storage locker that the previous tenant never cleaned out.
calloc — Clean Memory
calloc(count, size) allocates space for count items of size bytes each, and sets every byte to zero. It's like renting a locker that's been freshly swept. Use this when you want an array initialized to zero.
Dynamic Array with malloc vs calloc
realloc — Growing and Shrinking
What if you allocated space for 5 items but now need 10? That's where realloc comes in. It takes an existing allocation and resizes it — possibly moving the data to a new location if the current block can't grow in-place.
Think of it like asking the warehouse manager: "I need a bigger shelf." They might extend your current shelf, or they might move everything to a bigger one across the room and hand you the new address.
Growing an Array with realloc
Dangling Pointers
After you free(p), the memory is returned to the system — but p still holds the old address. Using p after freeing it is like going back to your old apartment after moving out and trying to sit on the couch. The couch might still be there... or someone else might be living there now. This is a dangling pointer — it points to memory that's no longer yours.
Best practice: set the pointer to NULL after freeing.
Proper Cleanup Pattern
Stack vs Heap — When to Use Which
Use the stack (normal variables) when:
- You know the size at compile time
- The data is small (a few ints, a small array)
- The data only needs to live inside one function
Use the heap (malloc/calloc) when:
- You don't know the size until runtime (user input decides)
- The data is large (thousands of elements)
- The data needs to outlive the function that created it
arr = realloc(arr, newSize). If realloc fails, it returns NULL and you lose your only reference to the original memory — instant memory leak! Always use a temp pointer.