如果我定义一个具有特定对齐要求的简单类型,那么所述类型的std::vector<t>
是否应该尊重每个元素的对齐?
考虑以下示例
typedef std::array<double,3> alignas(32) avx_point;
std::vector<avx_point> x(10);
assert(!(std::ptrdiff_t(&(x[0]))&31) && // assert that x[0] is 32-byte aligned
!(std::ptrdiff_t(&(x[1]))&31)); // assert that x[1] is 32-byte aligned
我发现对齐要求是由clang 3.2(有或没有-stdlib=libc++
)默认(没有任何警告),而gcc 4.8.0发出警告,忽略模板参数{}的属性{1}}(英特尔编译器太愚蠢而无法理解std::vector
,但如果我使用alignas
代替它,它的行为就像铿锵声)。两者都创建触发断言的代码。
那么,这是正确的行为还是clang(和icpc)的错误以及gcc的问题?
修改 回答评论中提出的问题:如果我定义
__declspec(align(32))
我得到了
typedef typename std::aligned_storage<sizeof (avx_point),
alignof(avx_point)>::type avx_storage;
但是sizeof (avx_storage) == 32;
alignof(avx_storage) == 32;
仍然无法对齐clang和gcc的第一个元素(因此也是所有其他元素)(此时没有警告)。因此,实现显然存在两个问题:首先,即使对于第一个元素(非法?),std::vector<avx_storage>
也忽略了任何对齐要求,其次,没有应用填充来确保后续元素的对齐。
答案 0 :(得分:3)
首先,即使对于第一个元素(非法?)
,std :: allocator也会忽略任何对齐要求
我远不是分配器专家,但在我看来,不幸的是,这是合法行为。更确切地说,分配器可能会忽略请求的对齐。的确,[allocator.requirements],17.6.3.5 / 6表示:
如果分配器不支持与特定的过度对齐类型关联的对齐,则实例化 该类型的分配器可能会失败。 分配器也可以默默地忽略请求的对齐。
您可以编写自己的分配器来为您提供对齐的内存。我在工作之前已经这样做了,但不幸的是,出于版权原因,我无法透露代码:-(我只能说,这是显而易见的事情:它基于_aligned_malloc
和_aligned_free
(这是微软的扩展)。或者你可以谷歌“对齐分配器”,并会出现一些选项,其中一个是
https://gist.github.com/donny-dont/1471329
我强调我不是这个对齐的分配器的作者,我从来没有使用它。
<强>更新强>
上面的对齐分配器适用于Visual Studio / Windows,但它可以用作在其他平台上实现对齐分配器的基础。您可以使用posix memalign
函数族或C11函数aligned_alloc
。
请参阅this帖子。