Dynamic memory is powerful, but C trusts you completely. These are the classic mistakes:
| Mistake | What happens | Habit that prevents it |
|---|---|---|
Forgetting free | Memory leak: the program uses more and more memory | Write the free as soon as you write the malloc |
Using memory after free | Random wrong values or crashes | Set the pointer to NULL right after freeing |
| Freeing twice | Crash | Set the pointer to NULL after freeing |
| Writing past the end | Overwrites other data, strange bugs | Keep the size in a variable and loop with i < size |
Forgetting sizeof | malloc(n) gives n bytes, not n ints | Always write n * sizeof(type) |
A safe pattern
#include <stdio.h>
#include <stdlib.h>
int main() {
int size = 4;
int *data = malloc(size * sizeof(int));
if (data == NULL) {
return 1;
}
for (int i = 0; i < size; i++) {
data[i] = i * i;
}
printf("Last: %d\n", data[size - 1]);
free(data);
data = NULL; // now nobody can use the old memory by accident
printf("Freed safely\n");
return 0;
}Output
Last: 9 Freed safely
Strings on the heap
Strings work the same way. Remember the extra place for '\0':
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char word[20] = "dynamic";
char *copy = malloc(strlen(word) + 1); // +1 for '\0'
strcpy(copy, word);
copy[0] = 'D';
printf("%s / %s\n", word, copy);
free(copy);
return 0;
}Output
dynamic / Dynamic
Common mistake:
malloc(strlen(word))without the+ 1. There's no room for'\0', so the string runs over the end of its memory.
Tip: On your own computer, tools like
valgrindor gcc's-fsanitize=addressoption find these mistakes for you.