【问题标题】:What would cause _mm_setzero_si128() to SIGSEGV? [duplicate]什么会导致 _mm_setzero_si128() 到 SIGSEGV? [复制]
【发布时间】:2012-07-25 03:03:31
【问题描述】:

可能重复:
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 指令会被完全优化掉,程序运行良好。正如 cmets 中已经指出的那样,这似乎毕竟是堆栈的对齐问题。

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

【问题讨论】:

  • 你有没有试过反汇编看看这两种情况在低层发生了什么?
  • _mm_setzero_si128 根本不应该触及内存..
  • 什么是导致段错误的 asm 指令,它的参数是什么?这也可能是对齐问题。
  • 很确定这是对齐问题。 zero 变量会溢出到堆栈的某处,由于某种原因未对齐。我曾经在 Windows 中使用 64 位 mingw 时遇到过类似的问题。
  • 使用对齐的存储溢出到未对齐的堆栈位置将是一个严重的编译器错误,应该报告。

标签: c++ multithreading wxwidgets sse segmentation-fault


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 我想我不明白 setzero 的作用。从名字上我认为它是在清零一个内存区域。
    • @RafaelBaptista _mm_setzero_si128 是一个内置的 SSE2 内在函数。它应该是由编译器的标准库提供的,应该直接编译成一条或几条SSE2汇编指令。
    • @FredOverflow 它可以访问内存,特别是zero 可能位于堆栈上。 __m128i 类型应该使用编译器特定的对齐属性进行修饰。包含文件中的对齐属性与编译器的预期不匹配可能会导致此错误。此外,编译器可能会忽略对齐,使其不符合 SSE2。
    【解决方案3】:

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

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

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

    【讨论】:

    • 谢谢,它适用于-mstackrealign :) 有趣的是,当我搜索wxwidgets "mpreferred-stack-boundary" 时,我看到的所有结果都使用mpreferred-stack-boundary=2。这似乎是 WxWidgets 通常的构建方式:(
    • 看来-mstackrealign和等价的__attribute__((force_align_arg_pointer))只生成了一条额外的汇编指令,即andl $-16, %esp。我想我可以忍受。再次感谢!
    • 我把“-mstackrealign”放在哪里?
    猜你喜欢
    • 2010-12-06
    • 1970-01-01
    • 2014-04-26
    • 1970-01-01
    • 1970-01-01
    • 2021-10-20
    • 2020-08-31
    • 2011-06-29
    • 2016-07-29
    相关资源
    最近更新 更多