Step 8 of 10
Who owns what
C has no garbage collector, so for every heap block, some code must be responsible for freeing it: its owner. Most memory bugs come from confusion about ownership: two parts of the program each thinking the other will free something (a leak), or both freeing it (a double free).
Professional C code makes ownership explicit, usually in a comment next to the function:
/* Returns a new string. The caller owns it and must free() it. */
char *read_name(void);
/* Borrows s: does not keep or free it. */
int count_vowels(const char *s);
When a function returns something nested (an array of separately allocated strings, a tree of nodes), freeing it correctly requires several steps in the right order. Good libraries provide a matching free function so callers can't get it wrong.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Returns n heap copies of s in a heap array. Release with free_copies(). */
char **copies(const char *s, int n) {
char **out = malloc(n * sizeof *out);
if (!out) return NULL;
for (int i = 0; i < n; i++) {
out[i] = malloc(strlen(s) + 1);
if (!out[i]) {
while (i > 0) free(out[--i]);
free(out);
return NULL;
}
strcpy(out[i], s);
}
return out;
}
void free_copies(char **list, int n) {
for (int i = 0; i < n; i++) free(list[i]);
free(list);
}
int main(void) {
char **c = copies("hi", 3);
if (!c) return 1;
c[1][0] = 'H';
printf("%s %s %s\n", c[0], c[1], c[2]);
free_copies(c, 3);
return 0;
}
hi Hi hi
Splitting a string
To split on spaces, walk the string, find where each word starts and ends, allocate length + 1 bytes for it, copy the characters with memcpy, and add the '\0'. Count the words first (spaces + 1 for a non-empty string) so you know how big the array of pointers must be, or grow it with realloc as you go.
Your turn: write split_words. It splits s on single spaces into separately allocated strings, stores how many in *count, and returns the array. Then write free_words. You can assume words are separated by exactly one space and s has no leading or trailing spaces. An empty string has 0 words (you may return NULL then).
Previous: A 2D grid on the heap Next: Where a program's data lives