我找到了两种简单而充分的方法来对齐指针。可以找到扩展讨论here。 他们在这里:
void* allocate_align_1(size_t size, uintptr_t align)
{
void* addr = malloc(size + align);
uintptr_t aligned_addr = (uintptr_t)addr;
aligned_addr += align - (aligned_addr % align);
return (void*)aligned_addr;
}
void* allocate_align_2(size_t size, uintptr_t align)
{
void* addr = malloc(size + align);
uintptr_t aligned_addr = (uintptr_t)addr;
aligned_addr = (aligned_addr + (align - 1)) & -align;
return (void*)aligned_addr;
}
coliru上的链接。
我的问题是如何实现deallocate_align(void* addr, uintptr_t align)
功能?
malloc
返回的指针是否可以从addr
恢复并对齐align
?然后它应该传递给free
。
答案 0 :(得分:1)
如果指针(可能是对齐大小)是您唯一的信息,则需要在某处存储某种元数据(原始指针,对齐偏移等)。它可能在您分配的内存块之前,您可以在执行重新分配时访问它,或者在其他地方使用某些注册表(例如哈希表或映射),在那里您将存储元数据并在解除分配时根据地址检索它们。 / p>
一种可能的(过度简化的)实现(未经测试,仅用于说明 - 在实际情况下,如果align
小于{{1}的合适对齐,则存储的值也需要正确对齐}):
uintptr_t
然后在deallocate中,您可以访问数据(为了正确使用,可能/应该检查一个保护值或类似物以确保正确的数据确实存在),这是一个没有检查的例子:
void* allocate_align_1(size_t size, uintptr_t align)
{
void* addr = malloc(size + align + sizeof(uintptr_t));
uintptr_t aligned_addr = (uintptr_t)addr + sizeof(uintptr_t);
aligned_addr += align - (aligned_addr % align);
// store the original address
*(uintptr_t*)(aligned_addr - sizeof(uintptr_t)) = (uintptr_t)addr;
return (void*)aligned_addr;
}
答案 1 :(得分:0)
如果使用gnu C / C ++编译器,malloc已经对齐
在GNU系统中由malloc或realloc返回的块的地址是 总是8的倍数(或64位系统上的16)。
因此,如果处理器需要对齐 - 您需要对齐。
如果您需要非标准对齐,您还需要保留原始指针,例如:
typedef struct {
void *original;
void *aligned;
} mypointer;
void* allocate_align_(mypointer *p; size_t size, uintptr_t align)
{
p -> original = malloc(size + align);
...
//aligning code here
p ->aligned = ... //(some math & pointer operations) do not change the p -> original
return p- > aligned;
}
void align_free(mypointer *p)
{
free(p -> original);
}
这不是真正的代码没有错误检查等只是想法