什么会导致_mm_setzero_si128()到SIGSEGV?

时间:2012-07-26 13:49:24

标签: c++ multithreading wxwidgets sse sigsegv

  

可能重复:
  Qt, GCC, SSE and stack alignment

我正在将模拟器从TinyPTC转换为WxWidgets。一些图形例程使用SSE内在函数进行了优化。在GUI初始化期间,初始状态呈现一次,并且所有SSE例程都完美地工作。但是,如果我稍后从事件处理程序中调用它们,我会得到一个SIGSEGV。

起初我认为这些是一些奇怪的对齐问题,但它甚至发生在:

__m128i zero = _mm_setzero_si128();

当我用非优化代码替换SSE例程时,一切正常。

我认为事件处理发生在与初始化不同的线程中。从不同的线程使用SSE时有什么需要注意的吗?还有什么可能导致这种行为?


SIGSEGV发生在movdqa %xmm0, -40(%ebp)指令处(有几个指令)。如果我使用-O1进行编译,movdqa指令将完全优化,程序运行正常。毕竟,这似乎是堆栈的对齐问题,正如评论中已经指出的那样。

这是CodeLite为编译生成的命令:

g++ -c "x:/some/folder/sse.cpp" -g -O1 -Wall -std=gnu++0x -msse3
-mthreads -DHAVE_W32API_H -D__WXMSW__ -D__WXDEBUG__ -D_UNICODE
-ID:\CodeLite\wxWidgets\lib\gcc_dll\mswud -ID:\CodeLite\wxWidgets\include
-DWXUSINGDLL -Wno-ctor-dtor-privacy -pipe -fmessage-length=0 -o ./Debug/sse.o -I.

有什么不寻常的吗? WxWidgets是否可能在某处更改对齐设置?

3 个答案:

答案 0 :(得分:4)

您的堆栈指针可能未对齐。 SSE指令要求所有存储器位置都是16字节对齐的。 _mm_setzero_si128指令不会发生问题,它只是将常量加载到SSE寄存器中,而是编译器生成的用于将该寄存器存储回堆栈内存的指令。

首先确保您没有使用过时版本的GCC(旧版本存在与SSE堆栈对齐的问题)。然后,尝试为该转换单元添加-mstackrealign选项,这将强制将堆栈重新调整为函数入口上的16字节对齐(这会增加非常小的运行时成本)。

有关movdqa指令及其生成异常的确切条件的更多详细信息,请参阅Intel Architectures Software Developer Manuals的第2B卷第4-67页。

答案 1 :(得分:0)

AFAIK,wxWidgets事件处理在主线程(GUI线程)中运行。您应该能够通过在调试器中运行来确认。调试器还应提供有关段故障发生位置的一些提示。

答案 2 :(得分:0)

您可能在SSE例程中有错误。 SSE指令将以更大的块写入数据。在使用SSE将其清零时,可能会超出阵列的末尾。例如。检查清零数组是否不是8字节的倍数。因此,您可能希望使用非优化指令对数组进行任何奇数结束。