Advanced Pointers
Ownership Transfer
Passing a pointer slot can hand heap ownership to a cleanup helper.
owner pointer
One pointer variable is responsible for freeing heap storage.
clear after free
Setting the caller's pointer to `0` after `free` prevents accidental reuse.
Ownership Transfer
ownership_transfer.c
Replay: real traced execution (multi-file project)
#include <stdio.h>
#include <stdlib.h>
static void release(int **owner) {
free(*owner);
*owner = 0;
}
int main(void) {
int value = 6;
int *owned = (int *)malloc(sizeof(int));
*owned = value;
int before = *owned;
release(&owned);
printf("before=%d released=%d\n", before, owned == 0);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
static void release(int **owner) {
free(*owner);
*owner = 0;
}
int main(void) {
int value = 9;
int *owned = (int *)malloc(sizeof(int));
*owned = value;
int before = *owned;
release(&owned);
printf("before=%d released=%d\n", before, owned == 0);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
static void release(int **owner) {
free(*owner);
*owner = 0;
}
int main(void) {
int value = 12;
int *owned = (int *)malloc(sizeof(int));
*owned = value;
int before = *owned;
release(&owned);
printf("before=%d released=%d\n", before, owned == 0);
return 0;
}
value ← 6, owned ← ⟨addr A⟩, before ← 6
9int main(void) {10 int value→ 6 = 6; //@value=9, 1211 int *owned→ ⟨addr A⟩ = (int *)malloc(sizeof(int));12 *owned⟨addr A⟩ = value6;13 int before→ 6 = *owned⟨addr A⟩;1415 release(&owned⟨addr A⟩);static void release(int **owner)
4static void release(int **owner⟨addr B⟩) {5 free(*owner⟨addr B⟩);6 *owner⟨addr B⟩ = 0;7}owned ← 0
15 release(&owned→ 0);1617 printf("before=%d released=%d\n", before6, owned0 == 0);18 return 0;19}outputbefore=6 released=1
value ← 9, owned ← ⟨addr A⟩, before ← 9
9int main(void) {10 int value→ 9 = 9;11 int *owned→ ⟨addr A⟩ = (int *)malloc(sizeof(int));12 *owned⟨addr A⟩ = value9;13 int before→ 9 = *owned⟨addr A⟩;1415 release(&owned⟨addr A⟩);static void release(int **owner)
4static void release(int **owner⟨addr B⟩) {5 free(*owner⟨addr B⟩);6 *owner⟨addr B⟩ = 0;7}owned ← 0
15 release(&owned→ 0);1617 printf("before=%d released=%d\n", before9, owned0 == 0);18 return 0;19}outputbefore=9 released=1
value ← 12, owned ← ⟨addr A⟩, before ← 12
9int main(void) {10 int value→ 12 = 12;11 int *owned→ ⟨addr A⟩ = (int *)malloc(sizeof(int));12 *owned⟨addr A⟩ = value12;13 int before→ 12 = *owned⟨addr A⟩;1415 release(&owned⟨addr A⟩);static void release(int **owner)
4static void release(int **owner⟨addr B⟩) {5 free(*owner⟨addr B⟩);6 *owner⟨addr B⟩ = 0;7}owned ← 0
15 release(&owned→ 0);1617 printf("before=%d released=%d\n", before12, owned0 == 0);18 return 0;19}outputbefore=12 released=1
Exercise: ownership_transfer.c
Move heap ownership into a cleanup helper and prove the caller cannot free the same pointer twice