我最近修复了一个错误,其中结构的__declspec(align(64))
成员因为分配结构的内存的方式而未对齐。所以,我正在寻找解决这种情况的方法。
例如,请考虑以下结构:
struct foo {
__declspec(align(64)) int bar[BAZ_LEN];
int baz;
};
如果在堆栈上分配,编译器将负责对齐。如果通过malloc()
分配,则无效。如果出于性能或正确性原因(或两者)依赖于对齐,这将破坏访问bar的代码。
所以,问题是:处理这种情况的最佳方法是什么?在我的情况下struct foo
对于我的组件的所有“私有”功能都可以被视为不透明。
澄清/更新的。非常感谢你的答案。我应该事先说过,但问题是我的struct的用户分配了一块内存并将其分成多个部分,其中一个是foo_t
structus的数组。该数组的偏移量不是常数,因此对齐起始地址可能没有帮助。我正在寻找一种方法来允许这样使用我的结构,同时保留一些对齐假设。
我现在想到的解决方案(尚未尝试过)是添加填充成员:
struct foo {
__declspec(align(64)) int bar[BAZ_LEN];
int baz;
char padding[64];
};
并且在每个函数中执行以下操作(包装在宏中):
void f(foo_t *foo_)
{
foo_t *foo = (foo_t *)(((uintptr_t)foo_ & ~63) + 64);
...
}
这会浪费每个结构64个字节,这在我的情况下不是问题。由于从不访问填充成员,因此移位不会导致任何段错误。然而,这个解决方案增加了相当多的心理开销,因为必须为每个公共函数清理对齐...
答案 0 :(得分: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);
描述
2aligned_alloc
函数为对齐的对象分配空间 由alignment指定,其大小由size指定,其值为 不定。对齐的值应该是由支持的有效对齐 实现和大小的值应该是对齐的整数倍。返回
3aligned_alloc
函数返回空指针或指向已分配的指针 空间。
或者你可以使用POSIX posix_memalign()
:
NAME
posix_memalign
- 对齐的内存分配(ADVANCED REALTIME)概要
#include <stdlib.h> int posix_memalign(void **memptr, size_t alignment, size_t size); [Option End]
说明
posix_memalign()
函数应在size
指定的边界上分配alignment
个字节,并在memptr
中返回指向已分配内存的指针。alignment
的值应为sizeof(void *)的两倍的幂。成功完成后,
memptr
指向的值应为对齐的倍数。如果请求的空间大小为0,则行为是实现定义的;
memptr
中返回的值应为空指针或唯一指针。free()函数应解除先前由posix_memalign()分配的内存。
返回值
成功完成后,
posix_memalign()
将返回零;否则,应返回错误编号以指示错误。
请注意,没有aligned_realloc()
也没有POSIX等价物。
答案 1 :(得分:4)
您可以使用posix_memalign进行动态对齐分配。在C11中,存在记忆对准控制,例如, this博客中的“记忆对齐控制”。