Fundamentals 53 min read

Unveiling malloc: How C Allocates Memory Behind the Scenes

This comprehensive guide explains the inner workings of the C malloc function, covering memory layout, stack vs heap, glibc memory pools, system calls like brk/sbrk and mmap, allocation strategies, fragmentation, alignment, multithreading safety, and comparisons with calloc, realloc, and C++ new.

Deepin Linux
Deepin Linux
Deepin Linux
Unveiling malloc: How C Allocates Memory Behind the Scenes

In C and low‑level development, malloc is the core entry for dynamic memory allocation, yet many developers only use it without understanding how memory is actually allocated.

1. Basics of Memory Layout

A typical C program’s address space consists of several segments:

Code segment : read‑only compiled instructions.

Data segment : global and static variables (initialized and BSS).

Stack segment : automatic local variables, function parameters, return addresses; managed in LIFO order.

Heap segment : memory obtained via malloc, calloc, realloc, and released with free.

Understanding this layout is essential before diving into malloc.

2. Introducing malloc

malloc

is declared in <stdlib.h> as void* malloc(size_t size). It returns a pointer to size bytes or NULL on failure. The pointer must be cast to the appropriate type before use.

Typical Use Cases

Dynamic arrays : allocate an array when the size is unknown at compile time and resize with realloc.

Linked lists : allocate each node with malloc and link them.

Complex structures (trees, graphs) : allocate nodes on demand.

3. Interaction with the Operating System

glibc Memory Pool

On Linux, malloc does not call the kernel directly for every request. Instead, glibc maintains a user‑space memory pool. If the pool has a suitable free block, malloc returns it without a system call, greatly reducing overhead.

brk / sbrk

When the pool lacks space, malloc may invoke brk (or its wrapper sbrk) to extend the program’s data segment. This moves the program break upward, allocating contiguous virtual memory pages on demand.

mmap

For large allocations (typically >128 KB), malloc prefers mmap to create an independent anonymous mapping. mmap avoids heap fragmentation and allows the kernel to release the region with munmap when freed.

4. malloc’s Internal Mechanisms

Memory Pools

glibc reserves a large chunk of memory from the kernel at startup (e.g., 1 MiB) and serves small allocations from this pool, similar to a supermarket’s inventory.

Free‑Block Management

Two common schemes are used:

Free‑list : a linked list of free blocks; allocation scans the list (first‑fit, best‑fit) and may split a larger block.

Buddy system : blocks are powers of two; splitting and merging maintain alignment and reduce external fragmentation.

Slab allocator : pre‑creates slabs of fixed‑size objects for high‑frequency allocations (e.g., kernel inode structures).

Allocation Flow

Check the memory pool for a suitable free block.

If none, search the free‑list or buddy system.

If still none, invoke brk for small requests or mmap for large ones.

Align the returned address to the platform’s alignment requirement (4 bytes on 32‑bit, 8 bytes on 64‑bit).

Return the pointer; on failure, return NULL.

free() Flow

Mark the block as free.

Attempt to merge with adjacent free blocks (or buddy).

If the block belongs to an mmap region and meets size thresholds, call munmap to return memory to the kernel; otherwise, keep it in the pool.

5. Optimization Strategies

Allocation Policies

Small allocations (≤128 KB) use brk and the internal pool, while large allocations (>128 KB) use mmap to avoid heap fragmentation and enable immediate release.

Alignment

malloc ensures the returned address satisfies the strictest alignment among the requested type. For a struct containing char, int, and short, the overall alignment is 4 bytes, leading to padding that increases the struct size from 7 bytes to 12 bytes.

Fragmentation Reduction

Free‑list merging, buddy coalescing, and occasional heap compaction (rare due to pointer‑relocation complexity) mitigate internal and external fragmentation.

6. malloc in Multithreaded Environments

Thread‑Safety Issues

Concurrent malloc / free calls can corrupt global data structures, cause race conditions, and produce inconsistent views due to CPU caches.

Solutions

Global mutex : protect the allocator with a pthread_mutex_t. Simple but can become a bottleneck.

Spinlock : busy‑wait for short critical sections, avoiding context switches.

Thread‑Local Cache (TLC) : each thread maintains a private pool; only when the local cache is empty or full does it lock the global pool.

Best Practices

Always check the return value of malloc before dereferencing.

Pair every malloc with a matching free to avoid leaks.

Initialize allocated memory (e.g., with memset or calloc) before use.

After free, set the pointer to NULL to prevent dangling pointers.

7. Comparing malloc with Other Allocation Functions

malloc vs. calloc

malloc

allocates uninitialized memory; calloc allocates and zero‑fills it. calloc takes two arguments (element count and size) and is convenient when zero‑initialization is required.

malloc vs. realloc

realloc

resizes an existing allocation, either expanding in place if adjacent free space exists or allocating a new block, copying data, and freeing the old block.

malloc vs. C++ new

new

allocates from the C++ free store, automatically calls constructors, returns a typed pointer, and throws std::bad_alloc on failure (unless nothrow is used). malloc returns void*, requires explicit casts, does not invoke constructors, and signals failure with NULL.

When working with C++ objects, new should be preferred; malloc remains useful for raw buffers or interfacing with C libraries.

C programmingmallocmemory allocationglibcheap management
Deepin Linux
Written by

Deepin Linux

Research areas: Windows & Linux platforms, C/C++ backend development, embedded systems and Linux kernel, etc.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.