c-是否有一种方法可以保证malloc()结构的成员对齐



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

例如,考虑以下结构:

struct foo {
__declspec(align(64)) int bar[BAZ_LEN];
int baz;
};

如果在堆栈上分配,编译器将负责对齐。如果通过malloc()分配,它将不起作用。如果出于性能或正确性的原因(或两者兼而有之)而依赖于对齐,这将破坏访问条的代码。

所以,问题是:处理这种情况的最佳方式是什么?在我的情况下,除了我的组件的"私有"功能外,struct foo可以被认为是不透明的。

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

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

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个字节,这在我的情况下不是问题。由于填充成员从未被访问过,所以移位不会导致任何segfault。然而,这种解决方案增加了相当多的心理开销,因为每个公共功能都必须对对齐进行消毒。。。

在标准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函数为对齐为的对象分配空间由对齐指定,其大小由大小指定,其值为不确定的校准值应为有效校准,并由实现和大小值应为对齐的整数倍。

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

或者您可以使用POSIXposix_memalign():

NAME

posix_memalign—对齐内存分配(高级实时)

简介

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

描述

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

成功完成后,memptr所指的值应为对准的倍数。

如果请求的空间大小为0,则行为由实现定义;在CCD_ 16中返回的值应该是空指针或唯一指针。

free()函数将释放先前由posix_mealign()分配的内存。

返回值

成功完成后,posix_memalign()将返回零;否则,应返回一个错误编号以指示错误。

请注意,既没有aligned_realloc(),也没有等效的POSIX。

您可以使用posix_meagn进行动态对齐分配。C11中有一个内存对齐控件,例如本博客中的"内存对齐控件"。