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);