5

可能重复:
Qt、GCC、SSE 和堆栈对齐

我正在将模拟器从 TinyPTC 转换为 WxWidgets。一些图形例程使用 SSE 内在函数进行了优化。在 GUI 的初始化过程中,初始状态被渲染一次,所有的 SSE 例程都可以正常工作。但是,如果我稍后从事件处理程序中调用它们,我会得到一个 SIGSEGV。

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

__m128i zero = _mm_setzero_si128();

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

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


SIGSEGV 发生在一条movdqa %xmm0, -40(%ebp)指令上(其中有几个)。如果我用 编译-O1movdqa指令会被完全优化掉,程序运行良好。正如评论中已经指出的那样,这似乎是堆栈的对齐问题。

这是 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 是否有可能在某处更改对齐设置?

4

3 回答 3

4

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

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

请参阅英特尔架构软件开发人员手册第 2B 卷第 4-67 页,了解有关movdqa指令的更多详细信息以及它可以生成异常的确切条件。

于 2012-07-26T15:26:04.670 回答
0

AFAIK,wxWidgets 事件处理在主线程(GUI 线程)中运行。您应该能够通过在调试器中运行来确认这一点。调试器还应该给出一些关于段错误发生位置的提示。

于 2012-07-26T13:54:33.633 回答
0

您可能在 SSE 例程中有错误。SSE 指令会将数据写入更大的块中。使用 SSE 将其归零时,您可能会超出数组的末尾。例如,检查归零数组是否不是 8 字节的倍数。因此,您可能希望使用未优化的指令来处理数组的任何奇数端。

于 2012-07-26T14:00:08.643 回答