How malloc Works
The heap and free lists.
How malloc Works is a free C Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What malloc Really Does
When you call malloc(n), the C library hands you a pointer to at least n usable bytes. But the heap is just a region of process memory the allocator manages on your behalf.
The allocator's job is bookkeeping: tracking which bytes are in use, which are free, and how to reuse freed memory efficiently.
The Heap Comes from the OS
The allocator does not create memory from nothing. It asks the operating system for large chunks via system calls like brk/sbrk or mmap.
Then it carves those chunks into smaller blocks for your malloc calls. Asking the OS is expensive, so allocators request memory in bulk and recycle it.
/* Conceptual: grow the heap by 4096 bytes */
void *base = sbrk(4096);
if (base == (void *)-1) {
/* out of memory */
}sbrk and the Program Break
sbrk(n) moves the "program break" up by n bytes and returns the previous break. That newly exposed region becomes available heap space.
It is linear and simple, but cannot easily return memory in the middle. Modern allocators prefer mmap for large requests.
void *prev_break = sbrk(0); /* current break */
sbrk(1024); /* grow by 1 KB */
/* prev_break now points to fresh memory */Block Metadata
For each allocation the allocator stores a small header next to the data: its size, and whether it is free. This header lets free work with just the data pointer you pass back.
The pointer you receive from malloc points after the header, so the metadata stays hidden from you.
typedef struct block {
size_t size;
int free;
struct block *next;
} block_t;Pointer Just After the Header
A common trick is pointer arithmetic: the user pointer is header + 1. Given a user pointer, the header is one block_t before it.
This is how free(p) recovers the size of the block you allocated without you ever passing it.
block_t *hdr = (block_t *)user_ptr - 1;
printf("block size = %zu\n", hdr->size);A Tiny Header Layout Demo
Let's lay a header over a static buffer and read it back. This shows how a real allocator splits a region into header plus payload.
No OS calls are involved, so it runs anywhere.
#include <stdio.h>
#include <stddef.h>
typedef struct { size_t size; int free; } block_t;
static char buffer[256];
int main(void) {
block_t *h = (block_t *)buffer;
h->size = 64;
h->free = 0;
void *payload = (char *)buffer + sizeof(block_t);
printf("header bytes = %zu\n", sizeof(block_t));
printf("payload offset = %ld\n", (long)((char *)payload - buffer));
printf("size field = %zu\n", h->size);
return 0;
}The Free List Idea
Many allocators thread free blocks into a linked list. When you call malloc, the allocator walks this list looking for a block big enough.
When you call free, the block is marked free and returned to the list for later reuse, avoiding another OS request.
block_t *find_free(block_t *head, size_t size) {
block_t *b = head;
while (b && !(b->free && b->size >= size))
b = b->next;
return b;
}What free Must Do
free(p) finds the header for p, marks it free, and ideally merges it with adjacent free blocks (coalescing) to fight fragmentation.
Calling free twice on the same pointer or freeing a non-heap pointer is undefined behavior, because the metadata becomes corrupt.
void my_free(void *p) {
if (!p) return;
block_t *hdr = (block_t *)p - 1;
hdr->free = 1;
/* real allocators coalesce neighbors here */
}Fragmentation
Over time, freeing and allocating different sizes leaves gaps. External fragmentation means free memory exists but is scattered in pieces too small to satisfy a request.
Internal fragmentation is wasted space inside a block that is bigger than needed, often due to alignment or rounding.
Alignment Requirements
malloc must return memory aligned for any type. On most 64-bit systems this means 16-byte alignment, satisfying max_align_t.
Misaligned pointers can crash on some CPUs or slow access on others, so allocators always round payloads up to an alignment boundary.
#include <stdalign.h>
/* alignof(max_align_t) is the strictest required alignment */
size_t a = alignof(max_align_t);Putting It Together
A minimal allocator therefore needs: a memory source (static buffer, sbrk, or mmap), per-block headers, a strategy to find free space, and alignment handling.
In the next lessons we build these pieces: first a bump allocator, then free lists, then alignment and block splitting.
/* The four pillars of a custom allocator */
/* 1. memory source 2. block headers */
/* 3. free-block search 4. alignment */Quick Check
Test your understanding of allocator internals.
Recap
malloc manages a heap obtained from the OS via sbrk or mmap, carving it into blocks with hidden headers that track size and free state.
Free lists enable reuse, alignment keeps every type happy, and fragmentation is the central challenge. These ideas drive the allocator we build next.
Frequently asked questions
Is the “How malloc Works” lesson free?
Yes — the full text of “How malloc Works” is free to read here on the web, and the C Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C Academy course, upgrade to CoddyKit PRO.
What will I learn in “How malloc Works”?
The heap and free lists. You practise C Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start C Academy?
No prior experience is required. C Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “How malloc Works” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this C Academy lesson?
Yes. Every C Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.