student@ubuntu:~$
c 4/5 40 XP

Dynamic Memory

0%

Quick Reference

Allocation functions:

Function Use Initializes?
calloc(count, size) Allocate array, zero-filled Yes (to 0)
malloc(total_bytes) Allocate raw bytes No (garbage)
realloc(ptr, new_size) Resize existing allocation No (new bytes are garbage)
free(ptr) Release memory back to OS N/A

The lifecycle:

1. Allocate:   int *arr = calloc(n, sizeof(int));
2. Check:      if (arr == NULL) { /* handle error */ }
3. Use:        arr[i] = value;
4. Free:       free(arr);
5. NULL out:   arr = NULL;

Safe realloc pattern:

int *temp = realloc(arr, new_size * sizeof(int));
if (temp == NULL) {
    free(arr);       // Clean up original on failure
    exit(1);
}
arr = temp;          // Only update after confirmed success

Memory layout:

High addresses
┌──────────────────┐
│      Stack       │  ← local variables (auto lifetime)
│        ↓         │
│    (free space)  │
│        ↑         │
│       Heap       │  ← calloc/malloc (manual lifetime)
├──────────────────┤
│    Data / BSS    │  ← globals
├──────────────────┤
│       Text       │  ← your compiled code
Low addresses

Common Pitfalls

  • Forgetting free() — Every calloc/malloc must have a matching free. Valgrind catches these as “definitely lost.”
  • Use-after-free — Accessing memory after free() is undefined behavior. Set pointer to NULL after freeing.
  • Double free — Calling free() twice on the same pointer corrupts the heap. NULL-check or set to NULL after free.
  • Wrong sizeofcalloc(n, sizeof(int *)) allocates pointer-sized slots (8 bytes), not int-sized (4 bytes). Match the type.
  • Direct realloc assignmentarr = realloc(arr, size) leaks on failure. Always use a temp variable.
  • Stack vs heap confusion — Returning a pointer to a local variable returns a dangling pointer. Use calloc for data that must outlive the function.

Unlocks

Complete this skill to see what it unlocks.