One of the golden rules of development in this ecosystem is that programmer-allocated memory must be freed.
Failure to do so leads to a bad situation – a bug, really – called memory leakage; this is covered in some depth in the next chapter. Carefully matching your allocations and frees is essential.
Using the free(3) API is straightforward:
void free(void *ptr);
It accepts one parameter: the pointer to the memory chunk to be freed. ptr must be a pointer returned by one of the malloc(3) family routines: malloc(3), calloc, or realloc[array].
free does not return any value; don't even attempt to check whether it worked; if you used it correctly, it worked. More on free is found in the Where does freed memory go? section. Once a memory chunk is freed, you obviously cannot attempt to use any part of that memory chunk again; doing so will result in a bug (or what's called UB – undefined behavior).
A common misconception regarding free() sometimes leads to its being used in a buggy fashion; take a look at this pseudocode snippet:
void *ptr = NULL;
[...]
while(<some-condition-is-true>) {
if (!ptr)
ptr = malloc(n);
[...
<use 'ptr' here>
...]
free(ptr);
}
This program will possibly crash in the loop (within the <use 'ptr' here> code) in a few iterations. Why? Because the ptr memory pointer is freed and is attempting to be reused. But how come? Ah, look carefully: the code snippet is only going to malloc(3) the ptr pointer if it is currently NULL, that is, its programmer has assumed that once we free() memory, the pointer we just freed gets set to NULL. This is not the case!!
Be wary and be defensive in writing code. Don't assume anything; it's a rich source of bugs. Importantly, our Chapter 19, Troubleshooting and Best Practices, covers such points)