Aligned Memory Allocation

hard · memory, alignment, optimization

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

  1. Allocate more than needed: size + alignment - 1 + sizeof(void*)
  2. Find the first aligned address within that region
  3. Store original pointer just before aligned address (for freeing)
  4. 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 - 1 to 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

  • alignment must be power of 2 (return NULL otherwise)
  • alignment must be >= sizeof(void*) to store original pointer
Run tests to see results
No issues detected