有没有办法保证malloc() - ed结构的成员对齐

kol*_*usa 7 c struct memory-alignment

我最近修复了一个错误,其中一个__declspec(align(64))结构的成员由于分配结构的内存的方式而未对齐.所以,我正在寻找解决这种情况的方法.

例如,请考虑以下结构:

struct foo {
    __declspec(align(64)) int bar[BAZ_LEN];
    int baz;
};
Run Code Online (Sandbox Code Playgroud)

如果在堆栈上分配,编译器将负责对齐.如果通过分配malloc(),它将无法工作.如果出于性能或正确性原因(或两者)依赖于其对齐,这将破坏访问bar的代码.

所以,问题是:处理这种情况的最佳方法是什么?在我的情况下struct foo,除了我的组件的"私有"函数之外的所有函数都可以认为是不透明的.

澄清/更新.非常感谢你的答案.我应该事先说过这个问题,但问题是我的struct的用户分配了一大块内存并将其分成多个部分,其中一个中间部分是一个foo_tstructus 数组.该数组的偏移量不是常数,因此对齐起始地址可能没有帮助.我正在寻找一种方法来允许这样使用我的结构,同时保留一些对齐假设.

我现在想到的解决方案(还没试过这个)是添加一个填充成员:

struct foo {
    __declspec(align(64)) int bar[BAZ_LEN];
    int baz;
    char padding[64];
};
Run Code Online (Sandbox Code Playgroud)

并且在每个函数中执行以下操作(包装在宏中):

void f(foo_t *foo_)
{
    foo_t *foo = (foo_t *)(((uintptr_t)foo_ & ~63) + 64);
    ...
}
Run Code Online (Sandbox Code Playgroud)

这会浪费每个结构64个字节,这在我的情况下不是问题.由于从不访问填充成员,因此移位不会导致任何段错误.然而,这个解决方案增加了相当多的心理开销,因为必须为每个公共函数清理对齐...

Jon*_*ler 6

在标准C11中,您可以使用aligned_alloc():

ISO/IEC 9899:2011

7.22.3.1 aligned_alloc函数

概要

#include <stdlib.h>  
void *aligned_alloc(size_t alignment, size_t size);
Run Code Online (Sandbox Code Playgroud)

说明
2该aligned_alloc函数为对象分配空间,该对象的对齐方式由alignment指定,其大小由size指定,其值不确定.对齐值应为实现支持的有效对齐,size的值应为对齐的整数倍.

返回
3该aligned_alloc函数返回空指针或指向已分配空间的指针.

或者您可以使用POSIX posix_memalign():

名称

posix_memalign - 对齐的内存分配(ADVANCED REALTIME)

概要

#include <stdlib.h>  
int posix_memalign(void **memptr, size_t alignment, size_t size); [Option End]
Run Code Online (Sandbox Code Playgroud)

描述

posix_memalign()函数应分配size在指定边界上对齐的字节alignment,并应返回指向已分配内存的指针memptr.值alignment应为sizeof(void*)的两倍的幂.

成功完成后,指向的值memptr应为对齐的倍数.

如果请求的空间大小为0,则行为是实现定义的; 返回的值memptr应为空指针或唯一指针.

free()函数应解除先前由posix_memalign()分配的内存.

返回值

成功完成后,posix_memalign()应归零; 否则,应返回错误编号以指示错误.

请注意,没有aligned_realloc()POSIX等价物.


Seb*_*ler 4

您可以使用posix_memalign进行动态对齐分配。C11中有一个内存对齐控制,例如博客中的“内存对齐控制”。