Allocation Failure, Fragmentation, and Alignment
This chapter covers three practical realities of dynamic allocation: failure handling, fragmentation, and alignment.
Why This Matters
Allocation can fail, and failing to handle it is a security and robustness bug. Fragmentation degrades long-running programs. Alignment requirements can make a seemingly valid pointer undefined behavior. These are not edge cases; they are everyday systems concerns.
Prerequisites
c.memory.2— malloc/calloc/realloc/free.
Core Concept
Allocation failure
malloc/calloc/realloc return NULL when they cannot satisfy a request. You must check every result. Failure may be recoverable (small request) or fatal (out of memory). Robust code always checks and propagates the error.
Fragmentation
The heap is a finite region. Over time, allocation and deallocation of varying sizes can leave the free space split into many small holes — fragmentation. The total free memory may be large, but no single hole is big enough for a request. This is a property of the allocation pattern, not a leak.
Alignment
The allocator returns memory aligned for any standard type. But:
- Over-aligned types (e.g.,
_Alignas(32)) needaligned_allocor
posix_memalign (platform-specific).
- Accessing an object through a misaligned pointer is UB.
Examples
Handling failure
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int *p = malloc(sizeof *p);
if (p == NULL) {
fputs("out of memory\n", stderr);
return 1;
}
*p = 5;
free(p);
return 0;
}
Over-aligned allocation (C11)
#include <stdlib.h>
#include <stdalign.h>
int main(void)
{
/* aligned_alloc: size must be a multiple of alignment */
float *buf = aligned_alloc(32, 32 * sizeof *buf);
if (buf == NULL) return 1;
/* buf is 32-byte aligned */
free(buf);
return 0;
}
aligned_alloc is C11. On POSIX, posix_memalign is an alternative.
How It Works
The allocator tracks free blocks. A request of size N finds a free block >= N; the block may be split, leaving a smaller free block. Repeated splits and coalescing failures cause fragmentation. Alignment is guaranteed by the allocator's internal padding, but only up to the standard type alignment.
Variations
Fragmentation-resistant strategies
Pools, arenas, and slab allocators (c.memory.5) reduce fragmentation by allocating fixed sizes or freeing in bulk.
alignment check idiom
You can verify a pointer is aligned with:
#include <stdint.h>
_Bool is_aligned(void *p, size_t a) {
return ((uintptr_t)p % a) == 0;
}
This is well-defined for the purposes of *checking* (the integer conversion is implementation-defined but yields the address value).
Common Mistakes
- Not checking allocation failure.
- Assuming the heap never fragments.
- Allocating over-aligned memory with
malloc(not guaranteed). - Dereferencing a misaligned pointer obtained from a packed struct or cast.
Undefined Behavior
- Dereferencing a misaligned pointer.
VERIFIED - Writing beyond an allocation (heap overflow) — often a symptom of
miscalculating alignment/size.
Portability
aligned_allocis C11;posix_memalignis POSIX;_aligned_mallocis
MSVC. They differ in argument order and failure behavior.
Under the Hood
The allocator rounds sizes up to an alignment boundary (often 8 or 16 bytes) and stores metadata in a header. Fragmentation is visible in allocator statistics (e.g., mallinfo on glibc).
Practical Usage
- Always handle NULL.
- Choose allocation sizes and lifetimes to minimize fragmentation (arenas for
short-lived groups, pools for fixed-size objects).
- Use
aligned_alloc/posix_memalignfor SIMD and DMA buffers.
Exercises
1. Write a program that deliberately requests a huge allocation and handles the NULL return. 2. Demonstrate a fragmentation scenario by allocating/freeing varying sizes and observing that a large request fails even though total free memory seems sufficient (this is hard to force portably; describe the reasoning). 3. Use aligned_alloc and verify the returned pointer is aligned.
Deep Challenge
Implement a fixed-size pool allocator that is immune to fragmentation for a single object size, and explain how it differs from a general-purpose allocator. Include alignment handling and failure behavior.
Related Concepts
c.memory.5— custom allocators.c.mem.alignment— alignment.c.sec.6— input validation (allocation sizes).
References
- ISO/IEC 9899:2018 §7.22.3 (allocation), §6.2.8 (alignment).
Verification
aligned_allocis C11.VERIFIED- Misaligned access is UB.
VERIFIED - Allocation failure returns NULL.
VERIFIED - No example was executed during generation unless noted. `Execution not
verified.`
Progress
- [ ] Read
- [ ] Understand
- [ ] Complete examples
- [ ] Complete exercises
- [ ] Complete deep challenge
Concept checkboxes
- [ ] Allocation failure handling
- [ ] Fragmentation
- [ ] Alignment and over-alignment
- [ ] aligned_alloc/posix_memalign
Mastery levels
| Concept | Current level (0–8) | Target level |
|---|---|---|
| c.mem.failure | 0 | 6 |
| c.mem.fragmentation | 0 | 6 |
| c.mem.alignment | 0 | 6 |