C/C++ Arena

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