Memory
Cleanup Path
A cleanup path releases allocated memory before returning from success or error branches.
single cleanup
One cleanup block can release resources after different branches set a status.
error branch
Even when work stops early, allocated storage still needs to be released.
Cleanup Path
cleanup_path.c
Replay: real traced execution (multi-file project)
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int failAfterAlloc = 0;
int *buffer = (int *)malloc(sizeof(int));
int status = 0;
if (buffer == 0) {
status = 1;
} else if (failAfterAlloc) {
status = 2;
} else {
*buffer = 7;
status = *buffer;
}
if (buffer != 0) {
free(buffer);
}
printf("status=%d\n", status);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int failAfterAlloc = 1;
int *buffer = (int *)malloc(sizeof(int));
int status = 0;
if (buffer == 0) {
status = 1;
} else if (failAfterAlloc) {
status = 2;
} else {
*buffer = 7;
status = *buffer;
}
if (buffer != 0) {
free(buffer);
}
printf("status=%d\n", status);
return 0;
}
failAfterAlloc ← 0, buffer ← ⟨addr A⟩, status ← 0
4int main(void) {5 int failAfterAlloc→ 0 = 0; //@failAfterAlloc=16 int *buffer→ ⟨addr A⟩ = (int *)malloc(sizeof(int));7 int status→ 0 = 0;status ← 7
12 status = 2;13} else {14 *buffer⟨addr A⟩ = 7;15 status→ 7 = *buffer⟨addr A⟩;16}if (buffer != 0)
18if (buffer⟨addr A⟩ != 0) {19 free(buffer⟨addr A⟩);20}printf("status=%d ", status);
22 printf("status=%d\n", status7);23 return 0;24}outputstatus=7
failAfterAlloc ← 1, buffer ← ⟨addr A⟩, status ← 0
4int main(void) {5 int failAfterAlloc→ 1 = 1;6 int *buffer→ ⟨addr A⟩ = (int *)malloc(sizeof(int));7 int status→ 0 = 0;status ← 2
10 status = 1;11} else if (failAfterAlloc1) {12 status→ 2 = 2;13} else {if (buffer != 0)
18if (buffer⟨addr A⟩ != 0) {19 free(buffer⟨addr A⟩);20}printf("status=%d ", status);
22 printf("status=%d\n", status2);23 return 0;24}outputstatus=2
Exercise: cleanup_path.c
Add an early error branch that still releases every allocated buffer before returning