上交所和中证所容器

发布于 2024-10-20 08:44:55 字数 452 浏览 5 评论 0原文

以下代码出现段错误是否有明显的原因?

#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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

雪若未夕 2024-10-27 08:44:55

显然,如果 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 中的措辞):

分配函数尝试分配请求的存储量。如果成功的话,应该
返回存储块的起始地址,其长度(以字节为单位)至少应等于
要求的尺寸。从返回时分配的存储内容没有限制
分配函数。通过连续调用分配的存储的顺序、连续性和初始值
分配函数未指定。返回的指针应适当对齐,以便可以转换
指向具有基本对齐要求(3.11)的任何完整对象类型的指针,然后使用
访问分配的存储中的对象或数组(直到通过调用显式释放存储
相应的释放函数)。

[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 of std::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):

The allocation function attempts to allocate the requested amount of storage. If it is successful, it shall
return the address of the start of a block of storage whose length in bytes shall be at least as large as
the requested size. There are no constraints on the contents of the allocated storage on return from the
allocation function. The order, contiguity, and initial value of storage allocated by successive calls to an
allocation function are unspecified. The pointer returned shall be suitably aligned so that it can be converted
to a pointer of any complete object type with a fundamental alignment requirement (3.11) and then used
to access the object or array in the storage allocated (until the storage is explicitly deallocated by a call to
a corresponding deallocation function).

And [basic.align] says:

Additionally, a request for runtime allocation of dynamic storage for which the
requested alignment cannot be honored shall be treated as an allocation failure.

Can you try a newer version of gcc where this might be fixed?

街道布景 2024-10-27 08:44:55

您使用的 vector 构造函数实际上是这样定义的:(

explicit vector ( size_type n, const T& value= T(), const Allocator& = Allocator() );

参见例如 http://www.cplusplus.com/reference/stl/vector/vector/)。

换句话说,一个元素是默认构造的(即,调用构造函数时的默认参数值),然后通过复制第一个元素来创建其余元素。我的猜测是,您需要一个 point 的复制构造函数来正确处理 __m128i 值的(非)复制。

更新:当我尝试使用 Visual Studio 2010(v. 10.0.30319.1)构建您的代码时,我收到以下构建错误:

error C2719: '_Val': formal parameter with __declspec(align('16')) won't be aligned c:\program files\microsoft visual studio 10.0\vc\include\vector 870 1   meh

这表明 Ben 认为这是一个对齐问题,这是正确的。

The vector constructor you are using is actually defined like this:

explicit vector ( size_type n, const T& value= T(), const Allocator& = Allocator() );

(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:

error C2719: '_Val': formal parameter with __declspec(align('16')) won't be aligned c:\program files\microsoft visual studio 10.0\vc\include\vector 870 1   meh

This suggests Ben is right on the money regarding this being an alignment problem.

久隐师 2024-10-27 08:44:55

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 for std::vector<>, which handles dynamic memory allocation, does not produce aligned allocations.

夏九 2024-10-27 08:44:55

编译器 STL 实现中默认分配器分配的内存可能未对齐。这将取决于特定的平台和编译器供应商。

通常默认分配器使用运算符new,它通常不保证超出字大小(32 位或64 位)的对齐。为了解决这个问题,可能需要实现一个使用_aligned_malloc的自定义分配器。

另外,一个简单的修复(尽管不是令人满意的修复)是将值分配给本地 __m128i 变量,然后使用未对齐的指令将该变量复制到结构中。例子:

struct point {
    __m128i v;
    point() {
        __m128i temp = _mm_setr_epi32(0, 0, 0, 0);
        _mm_storeu_si128(&v, temp);
    }
};

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:

struct point {
    __m128i v;
    point() {
        __m128i temp = _mm_setr_epi32(0, 0, 0, 0);
        _mm_storeu_si128(&v, temp);
    }
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文