Aligned Memory Allocation
Aligned Memory Allocation
Return a payload with a requested power-of-two alignment while preserving the
original allocation for the paired free. The supplied my_malloc is a limited,
single-threaded teaching allocator with 8-byte rounding on the course's 64-bit
Linux target. That policy is not the standard C allocation contract: standard
allocation provides fundamental alignment, rather than one universal byte count.
Your interface
int is_power_of_two(size_t n);
size_t align_up(size_t n, size_t alignment);
void *my_aligned_alloc(size_t alignment, size_t size);
void my_aligned_free(void *ptr);
is_power_of_tworeturns 1 exactly for positive powers of two, otherwise 0.align_upreturns the least multiple ofalignmentgreater than or equal ton. Return 0 for invalid alignment or an unrepresentable rounded result.align_up(0, 8)also legitimately returns 0. This helper does not allocate.my_aligned_allocrejects zero size and invalid alignment withNULL. Promote a valid alignment smaller thansizeof(void*)tosizeof(void*), so the saved original-pointer slot is suitably aligned on this target. The requested size need not be a multiple of alignment; this is a custom API.- On success, all
sizepayload bytes must be writable, disjoint from the saved pointer, and preserved until the paired free. Separate live allocations cannot overlap. Allocation does not promise zeroed bytes. - Reject overflow in padding, pointer-slot addition, base-allocator rounding,
header addition, or conversion to the signed
sbrkincrement. Rejected arithmetic makes no growth call and changes no existing block, list link, or live data. A growth failure also returnsNULLwithout changing existing allocations. my_aligned_free(NULL)does nothing. Every other input must be a live pointer returned bymy_aligned_alloc; interior pointers, foreign pointers, and double frees are outside the contract. Recover and free its original allocation.
Derive the layout
Reserve size + (effective_alignment - 1) + sizeof(void*) bytes from the
provided allocator, checking each addition before computing it. The first
part of that allocation leaves room for the saved pointer. Round the address
then save the original pointer immediately before the aligned payload.
Advance within the acquired region; do not wrap an integer address while rounding.
raw allocation start aligned payload
| optional padding | saved raw pointer | size writable bytes | spare bytes |
For an invented raw address 1000, an eight-byte pointer, alignment 64, and size
20: begin the search at 1008, round to 1024, store the original pointer in
[1016,1024), and return 1024. The caller owns [1024,1044); the paired free
recovers 1000. The underlying header lies before the raw allocation, outside
these reserved payload bytes.
Check the boundaries
For a power-of-two alignment, (n + alignment - 1) & ~(alignment - 1) works
only when the addition is representable. Check
n <= SIZE_MAX - (alignment - 1) first. With a toy maximum 255, rounding 250
to 8 would need 256 and must report failure rather than wrapping to zero and
using a small allocation. A successful small allocation is not evidence that
the original large request was satisfied.
Test sizes around an alignment boundary, promoted small alignments, invalid alignments, arithmetic rejection, writable payloads, and reuse after the paired free. The hidden tests use bounded simulated growth to check failure and unchanged ownership without trying to exhaust real memory.