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

failAfterAlloc
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;
}
  1. 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;
  2. status ← 7

    12    status = 2;13} else {14    *buffer⟨addr A⟩ = 7;15    status→ 7 = *buffer⟨addr A⟩;16}
  3. if (buffer != 0)

    18if (buffer⟨addr A⟩ != 0) {19    free(buffer⟨addr A⟩);20}
  4. printf("status=%d ", status);

    22    printf("status=%d\n", status7);23    return 0;24}
    outputstatus=7
  1. 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;
  2. status ← 2

    10    status = 1;11} else if (failAfterAlloc1) {12    status→ 2 = 2;13} else {
  3. if (buffer != 0)

    18if (buffer⟨addr A⟩ != 0) {19    free(buffer⟨addr A⟩);20}
  4. 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