上交所和中证所容器
以下代码出现段错误是否有明显的原因?
#include <vector>
#include <emmintrin.h>
struct point {
__m128i v;
point() {
v = _mm_setr_epi32(0, 0, 0, 0);
}
};
int main(int argc, char *argv[])
{
std::vector<point> a(3);
}
谢谢
编辑:我在 linux/i686 上使用 g++ 4.5.0,我可能不知道我在这里做什么,但因为即使出现以下段错误,
int main(int argc, char *argv[])
{
point *p = new point();
}
我真的认为它一定是对齐问题。
Is there an obvious reason why the following code segfaults ?
#include <vector>
#include <emmintrin.h>
struct point {
__m128i v;
point() {
v = _mm_setr_epi32(0, 0, 0, 0);
}
};
int main(int argc, char *argv[])
{
std::vector<point> a(3);
}
Thanks
Edit: I'm using g++ 4.5.0 on linux/i686, I might not know what I'm doing here, but since even the following segfaults
int main(int argc, char *argv[])
{
point *p = new point();
}
I really think it must be and alignment issue.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
显然,如果
v
未正确对齐,可能会出现错误。但它是由
vector
动态分配的,因此不会出现堆栈错位问题。然而,正如 phooji 正确指出的那样,“模板”或“原型”值被传递给 std::vector 构造函数,该构造函数将被复制到向量的所有元素。
std::vector::vector
的这个参数将被放置在堆栈上,并且可能会未对齐。一些编译器有一个用于控制函数内堆栈对齐的编译指示(基本上,编译器会根据需要浪费一些额外的空间来使所有本地变量正确对齐)。
根据 Microsoft 文档,Visual C++ 2010 应自动设置 8 字节堆栈对齐SSE 类型和自 Visual C++ 2003 以来就这样做了
对于海湾合作委员会我不知道。
在 C++0x 下,
new point()
返回未对齐的存储是严重的不合规行为。[basic.stc.dynamic.allocation]
说(草案 n3225 中的措辞):[basic.align]
说:你能尝试一个新版本的 gcc 来解决这个问题吗?
The obvious thing that could have gone wrong would be if
v
wasn't aligned properly.But it's allocated dynamically by
vector
, so it isn't subject to stack misalignment issues.However, as phooji correctly points out, a "template" or "prototype" value is passed to the
std::vector
constructor which will be copied to all the elements of the vector. It's this parameter ofstd::vector::vector
that will be placed on the stack and may be misaligned.Some compilers have a pragma for controlling stack alignment within a function (basically, the compiler wastes some extra space as needed to get all locals properly aligned).
According to the Microsoft documentation, Visual C++ 2010 should set up 8 byte stack alignment automatically for SSE types and has done so since Visual C++ 2003
For gcc I don't know.
Under C++0x, for
new point()
to return unaligned storage is a serious non-compliance.[basic.stc.dynamic.allocation]
says (wording from draft n3225):And
[basic.align]
says:Can you try a newer version of gcc where this might be fixed?
您使用的
vector
构造函数实际上是这样定义的:(参见例如 http://www.cplusplus.com/reference/stl/vector/vector/)。
换句话说,一个元素是默认构造的(即,调用构造函数时的默认参数值),然后通过复制第一个元素来创建其余元素。我的猜测是,您需要一个
point
的复制构造函数来正确处理__m128i
值的(非)复制。更新:当我尝试使用 Visual Studio 2010(v. 10.0.30319.1)构建您的代码时,我收到以下构建错误:
这表明 Ben 认为这是一个对齐问题,这是正确的。
The
vector
constructor you are using is actually defined like this:(see e.g., http://www.cplusplus.com/reference/stl/vector/vector/).
In other words, one element is default constructed (i.e., the default parameter value as you call the constructor), and the remaining elements are then created by copying the first one. My guess is that you need a copy constructor for
point
that properly handles the (non-)copying of__m128i
values.Update: When I try to build your code with Visual Studio 2010 (v. 10.0.30319.1), I get the following build error:
This suggests Ben is right on the money regarding this being an alignment problem.
SSE 内在函数在内存中需要 16 字节对齐。当您在堆栈上分配
__m128
时,不会有问题,因为编译器会自动正确对齐它们。std::vector<>
的默认分配器处理动态内存分配,不会产生对齐分配。SSE intrinsics are required to be 16-byte aligned in memory. When you allocate an
__m128
on the stack, there's no problem because the compiler automatically aligns these correctly. The default allocator forstd::vector<>
, which handles dynamic memory allocation, does not produce aligned allocations.编译器 STL 实现中默认分配器分配的内存可能未对齐。这将取决于特定的平台和编译器供应商。
通常默认分配器使用运算符
new
,它通常不保证超出字大小(32 位或64 位)的对齐。为了解决这个问题,可能需要实现一个使用_aligned_malloc
的自定义分配器。另外,一个简单的修复(尽管不是令人满意的修复)是将值分配给本地 __m128i 变量,然后使用未对齐的指令将该变量复制到结构中。例子:
There is a possibility that the memory that is allocated by the default allocator in your compiler's STL implementation is not aligned. This will be dependent on the specific platform and compiler vendor.
Usually the default allocator uses operator
new
, which usually does not guarantee alignment beyond the word size (32-bit or 64-bit). To solve the problem, it may be necessary to implement a custom allocator which uses_aligned_malloc
.Also, a simple fix (although not a satisfactory one) would be to assign the value to a local
__m128i
variable, then copy that variable to the struct using unaligned instruction. Example: