Reference code : https://embeddedartistry.com/blog/2017/02/22/generating-aligned-memory/
void * aligned_malloc(size_t align, size_t size)
{
void * ptr = NULL;
// We want it to be a power of two since
// align_up operates on powers of two
assert((align & (align - 1)) == 0);
if(align && size)
{
/*
* We know we have to fit an offset value
* We also allocate extra bytes to ensure we
* can meet the alignment
*/
uint32_t hdr_size = PTR_OFFSET_SZ (align - 1);
void * p = malloc(size hdr_size);
if(p)
{
/*
* Add the offset size to malloc's pointer
* (we will always store that)
* Then align the resulting value to the
* target alignment
*/
ptr = (void *) align_up(((uintptr_t)p PTR_OFFSET_SZ), align);
// Calc`enter code here`ulate the offset and store it
// behind our aligned pointer
*((offset_t *)ptr - 1) =
(offset_t)((uintptr_t)ptr - (uintptr_t)p);
} // else NULL, could not malloc
} //else NULL, invalid arguments
return ptr;
}
I do not understand how this line stores value behind the ptr. "*((offset_t *)ptr - 1) = (offset_t)((uintptr_t)ptr - (uintptr_t)p);"
CodePudding user response:
After the allocation and calculation, ptr
contains the value this routine will return to its caller, which is the address for the caller to use to store its data.
(offset_t *)ptr
converts this address to the type offset_t *
.
Then (offset_t *)ptr - 1
calculates a location in memory that is earlier (lower addressed) by the distance of one offset_t
object.
Then *((offset_t *)ptr - 1) = …;
stores a value in that location.
CodePudding user response:
In addition to other good answers:
ptr = (void *) align_up(((uintptr_t)p PTR_OFFSET_SZ), align);
lays the seeds for undefined behavior (UB) as aligned_malloc()
does not certainly meet max_align_t
.
malloc()
always provides a pointer that meets this requirement of aligning to at least sizeof(max_align_t)
and much code relies on that. aligned_malloc()
does not certainly meet that - it should.
Do not recommend this code "as is" for portability.
To do this right, aligned_malloc()
and align_up()
must consider the maximum of both max_align_t
and size
.
void * aligned_malloc(size_t align, size_t size) {
assert(...);
if (size < sizeof(max_algin_t)) {
size = sizeof(max_algin_t);
}
...