Introduction
Local variables live on the stack and disappear when their function returns. Sometimes you need memory whose size you learn only while the program runs, or that must outlive a function. For that, C has the heap.
So far, the size of everything has been known before the program runs. Real programs often cannot know that: how many lines does this file have? The heap lets you ask for exactly what you need, at the moment you need it, as long as you remember to give it back.
How it works
Leaks and dangling pointers
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *data = malloc(2 * sizeof(int));
data[0] = 1;
data[1] = 2;
data = malloc(4 * sizeof(int));
data[0] = 7;
free(data);
data[0] = 8;
return 0;
}When the last pointer to a block is lost, the block can never be freed: a memory leak. StepVioz marks such a block in red. Using a block after freeing it, or freeing it twice, is also an error; real C may crash much later or silently corrupt data, while StepVioz stops on the exact line.
Syntax
int *a = malloc(n * sizeof(int));
if (a == NULL) {
return 1;
}
int *b = realloc(a, 2 * n * sizeof(int));
free(b);
Example
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n = 3;
int *scores = malloc(n * sizeof(int));
if (scores == NULL) return 1;
for (int i = 0; i < n; i++) {
scores[i] = (i + 1) * 10;
}
int total = scores[0] + scores[1] + scores[2];
printf("total %d\n", total);
free(scores);
scores = NULL;
return 0;
}malloc(n * sizeof(int))asks for room fornints and returns its address (orNULLif there is no memory left).- The block appears under Heap in the memory panel, with
scorespointing to it. Its cells start as?: malloc does not clear them. free(scores)gives the block back. After that,scoresstill holds the old address, shown as dangling, so the program sets it toNULL.
calloc(n, size) is like malloc but sets every byte to 0. realloc(p, new_size) makes a block bigger or smaller.
Line by line
nis the number of elements, known only as the program runs.mallocasks for room for three ints, and returns its address.- The
ifhandles the rare case of no memory being available. - The loop fills the block, which is used just like an array.
freereturns the block, and settingscorestoNULLremoves the dangling address.
Expected result
total 60
In the real world
Browsers, games and servers allocate and release memory constantly, and leaks are a common reason for a long-running program slowing down. Whole languages, such as Rust, were designed to make these mistakes impossible.
Common mistakes
- Forgetting
free: every malloc needs exactly one free. - Using memory after
free, or calling free twice. Set the pointer toNULLafter free. malloc(n)when you meantmalloc(n * sizeof(int)): that is only n bytes.- Not checking for
NULLafter malloc.
Best practices
- Write the
freewhen you write themalloc. - Use
sizeofwith the type, rather than typing a number of bytes. - Keep a single clear owner for each block.
Summary
malloc gets memory from the heap at run time, and free returns it. realloc resizes a block. Each block must be freed exactly once, and used only while it is allocated.
Quick check
Key takeaways
- Every malloc needs exactly one free.
- Check the result of malloc for NULL.
- Set a pointer to NULL after freeing it.
Practice problems for this lesson
My notes
Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.