Aligned Memory Allocation
Aligned Memory Allocation
Standard malloc guarantees 8-byte alignment. But sometimes you need stronger guarantees:
- SIMD instructions (SSE/AVX) require 16/32/64-byte alignment
- DMA buffers may require page alignment (4096 bytes)
- Cache-line alignment (64 bytes) for performance
The Problem
void *p = my_malloc(100); // Might return 0x1004
// 0x1004 is NOT 32-byte aligned
// For SIMD, you need 0x1020 (next 32-byte boundary)
Your Task
Implement aligned allocation:
#define BLOCK_MAGIC 0xDEADBEEF
// Check if n is a power of 2
int is_power_of_two(size_t n);
// Round up n to next multiple of alignment
size_t align_up(size_t n, size_t alignment);
// Allocate 'size' bytes with 'alignment' byte alignment
void *my_aligned_alloc(size_t alignment, size_t size);
// Free an aligned allocation
void my_aligned_free(void *ptr);
Strategy
- Allocate more than needed:
size + alignment - 1 + sizeof(void*) - Find the first aligned address within that region
- Store original pointer just before aligned address (for freeing)
- Return the aligned pointer
Memory layout:
+----------+--------+----------------+---------------+
| orig_hdr | unused | orig_ptr store | aligned data |
+----------+--------+----------------+---------------+
^ ^ ^
original_ptr aligned-8 returned (aligned)
Critical Test: Alignment Must Be Correct
void *p = my_aligned_alloc(32, 100);
assert(p != NULL);
assert(((uintptr_t)p % 32) == 0); // Must be 32-byte aligned!
// Use the memory
memset(p, 0xAB, 100);
my_aligned_free(p); // Must find original pointer!
Finding Aligned Address
// alignment must be power of 2
uintptr_t addr = (uintptr_t)ptr;
uintptr_t aligned = (addr + alignment - 1) & ~(alignment - 1);
The formula works because:
- Add
alignment - 1to reach or pass next boundary - AND with
~(alignment - 1)clears lower bits (rounds down)
Storing Original Pointer
To free correctly, store the original pointer just before the aligned address:
// Store original just before aligned
void **ptr_storage = (void**)(aligned_addr - sizeof(void*));
*ptr_storage = original;
// Later, to free:
void *original = ((void**)aligned_ptr)[-1];
my_free(original);
Constraints
alignmentmust be power of 2 (return NULL otherwise)alignmentmust be >=sizeof(void*)to store original pointer
Run tests to see results
No issues detected