After a heap value has been read, free releases the storage back to the allocator.

release `free(ptr)` releases heap storage previously returned by `malloc`.
clear pointer Setting the pointer to `0` after `free` avoids accidentally reusing the old address.

Free Memory

value
free_memory.c
Replay: real traced execution (multi-file project)
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int value = 5;
    int *ptr = (int *)malloc(sizeof(int));

    if (ptr == 0) {
        return 1;
    }

    *ptr = value;
    int saved = *ptr;

    free(ptr);
    ptr = 0;

    printf("released=%d value=%d\n", ptr == 0, saved);
    return 0;
}
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int value = 8;
    int *ptr = (int *)malloc(sizeof(int));

    if (ptr == 0) {
        return 1;
    }

    *ptr = value;
    int saved = *ptr;

    free(ptr);
    ptr = 0;

    printf("released=%d value=%d\n", ptr == 0, saved);
    return 0;
}
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int value = 11;
    int *ptr = (int *)malloc(sizeof(int));

    if (ptr == 0) {
        return 1;
    }

    *ptr = value;
    int saved = *ptr;

    free(ptr);
    ptr = 0;

    printf("released=%d value=%d\n", ptr == 0, saved);
    return 0;
}
  1. value ← 5, ptr ← ⟨addr A⟩, saved ← 5

    4int main(void) {5    int value→ 5 = 5; //@value=8, 116    int *ptr→ ⟨addr A⟩ = (int *)malloc(sizeof(int));78    if (ptr == 0) {9        return 1;10    }1112    *ptr⟨addr A⟩ = value5;13    int saved→ 5 = *ptr⟨addr A⟩;1415    free(ptr⟨addr A⟩);16    ptr→ 0 = 0;1718    printf("released=%d value=%d\n", ptr0 == 0, saved5);19    return 0;20}
    outputreleased=1 value=5
  1. value ← 8, ptr ← ⟨addr A⟩, saved ← 8

    4int main(void) {5    int value→ 8 = 8;6    int *ptr→ ⟨addr A⟩ = (int *)malloc(sizeof(int));78    if (ptr == 0) {9        return 1;10    }1112    *ptr⟨addr A⟩ = value8;13    int saved→ 8 = *ptr⟨addr A⟩;1415    free(ptr⟨addr A⟩);16    ptr→ 0 = 0;1718    printf("released=%d value=%d\n", ptr0 == 0, saved8);19    return 0;20}
    outputreleased=1 value=8
  1. value ← 11, ptr ← ⟨addr A⟩, saved ← 11

    4int main(void) {5    int value→ 11 = 11;6    int *ptr→ ⟨addr A⟩ = (int *)malloc(sizeof(int));78    if (ptr == 0) {9        return 1;10    }1112    *ptr⟨addr A⟩ = value11;13    int saved→ 11 = *ptr⟨addr A⟩;1415    free(ptr⟨addr A⟩);16    ptr→ 0 = 0;1718    printf("released=%d value=%d\n", ptr0 == 0, saved11);19    return 0;20}
    outputreleased=1 value=11

Release Then Stop Using

  1. A pointer from malloc owns heap storage.
  2. Use the value while the storage is still allocated.
  3. Call free(ptr) once when the value is no longer needed.
  4. Set the pointer to 0 so later code does not reuse the old address.
allocated: ptr -> heap value
freed:     ptr -> old address is not safe
cleared:   ptr = 0

Exercise: free_memory.c

Free a malloc allocation, set the pointer to 0, and skip cleanup when the pointer is already null