如何自由对齐指针?

时间:2017-07-18 15:12:09

标签: c pointers memory-management alignment

我找到了两种简单而充分的方法来对齐指针。可以找到扩展讨论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

2 个答案:

答案 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);
    }

这不是真正的代码没有错误检查等只是想法