C Memory Management Patterns That Prevent Leaks

Disciplined memory management in C doesn't require a garbage collector — just consistent patterns.

Key Insights

  • Adopt an ownership convention: whoever allocates is responsible for freeing
  • Use goto-based cleanup for functions with multiple allocation points
  • Valgrind and AddressSanitizer catch leaks that code review misses

The Goto Cleanup Pattern

int process_file(const char *path) {
    int result = -1;
    FILE *fp = NULL;
    char *buffer = NULL;

    fp = fopen(path, "r");
    if (!fp) goto cleanup;

    buffer = malloc(BUF_SIZE);
    if (!buffer) goto cleanup;

    // ... do work ...
    result = 0;

cleanup:
    free(buffer);
    if (fp) fclose(fp);
    return result;
}

Ownership Convention

Document who owns allocated memory. The simplest rule: the caller allocates, the caller frees.

// Caller owns the returned buffer
char *read_all(FILE *fp, size_t *out_len);

// Function borrows the pointer — does not free
void process(const char *data, size_t len);

Liked this? There's more.

Every week: one practical technique, explained simply, with code you can use immediately.