【发布时间】:2018-08-24 08:27:08
【问题描述】:
根据question,我认为在 C++17 中,带有默认分配器的 std::vector 应该处理对齐的类型。但是,下面的代码
#include <iostream>
#include <iterator>
#include <array>
#include <vector>
template<typename T, size_t N, size_t Alignment>
struct alignas(Alignment) AlignedArray : public std::array<T, N>
{
friend std::ostream& operator<<(std::ostream& o, const AlignedArray& a)
{
std::copy(a.cbegin(), a.cend(), std::ostream_iterator<T>(o, " "));
return o;
}
};
int main()
{
using Array = AlignedArray<double, 24, 64>;
std::vector<Array> v(10);
for(const auto& e : v)
{
auto arr(e);
std::cout << arr << std::endl;
}
return 0;
}
当我使用 clang 6.0.1 和 -mavx 编译 arr 时出现段错误。如果没有-mavx 开关,它运行良好(CPU 是 E5-2697 v2)。我用它编译了
clang++ -I<path_to_libcxx>/include/c++/v1 -g -mavx -std=c++17 main.cpp -stdlib=libc++ -lc++abi -o alignastest -L<path_to_libcxx>/lib -L<path_to_libcxxabi>/lib。
我在旧的 RHEL 6.9 上运行它,我在其中编译了 clang 6.0.1 和 libcxx、libcxxabi。
我在另一个系统(Ubuntu 18.10,gcc 8)上对其进行了测试,它没有任何问题。
子问题
关于对齐,我发现 std::aligned_alloc 在 libc++ 中的实现依赖于 C11 功能,该功能仅在最近的 glibc 版本 (__config.h) 中启用:
#if __GLIBC_PREREQ(2, 17)
#define _LIBCPP_HAS_C11_FEATURES
#endif
不幸的是,RHEL 6.9 只安装了ldd (GNU libc) 2.12。 alignas 是否也取决于 glibc 版本?
【问题讨论】:
-
我在我的系统上对此进行了测试,适用于 g++ 8,不适用于 clang++ 6。我查看了编译后的程序,即使使用 -mavx 的 std::,g++ 也不使用 avx 指令:复制,而铿锵做。此外,指令错误是从第一个数组的地址到 ymm0 的 vmovaps(对齐的 256 位移动),希望这有助于调试。
-
我无法重现此内容。如果我使用
-std=c++17,我会得到一个正确对齐的内存块。 -
看来 libc++ 版本 6 中还没有对过度对齐类型的支持。
-
如何检查?
-
查看标题
并搜索有关对齐的任何内容。当前版本有很多,但在第 6 版中几乎没有。