繁体   English   中英

启用优化的奇怪行为

[英]Strange behavior with optimizations enabled

我有这个小代码片段(这是我遇到的问题的最小工作示例):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void xorBuffer(unsigned char* dst, unsigned char* src, int len)
{
    while (len != 0)
    {
        *dst ^= *src;
        dst++;
        src++;
        len--;
    }
}

int main()
{
    unsigned char* a = malloc(32);
    unsigned char* b = malloc(32);
    int t;

    memset(a, 0xAA, 32);
    memset(b, 0xBB, 32);

    xorBuffer(a, b, 32);

    printf("result = ");
    for (t = 0; t < 32; t++) printf("%.2x", a[t]);
    printf("\n");

    return 0;
}

该代码应该执行两个32字节内存缓冲区的异或(概念上,这应该执行a = a ^ b )。 由于0xAA ^ 0xBB = 0x11,它应该打印“11”三十二次。

我的问题是,当我在MinGW-GCC(Windows)下编译它时,这在调试模式下完美地工作(没有优化),但是当启用从-O3开始的优化时,在xorBuffer循环的中途与SIGILL崩溃。 此外,如果我在违规循环中放置一个printf,它将再次完美地工作。 我怀疑堆栈损坏,但我不知道我在这里做错了什么。

尝试使用启用了优化的GDB进行调试是一个失败的原因,因为所有GDB都会向我显示每个变量的“变量优化”(当然,如果我尝试将变量打印出来,它会突然起作用)。

有人知道这里发生了什么事吗? 我花了很长时间思考这个问题,我真的需要正确地修复它才能继续前进。 我的猜测是我缺少一些基本的C指针知识,但对我来说代码看起来是正确的。 它可以来自缓冲区增量,但据我所知, sizeof(unsigned char) == 1 ,所以它应该逐个遍历每个字节。

对于它的价值,即使在我的Linux机器上对GCC进行优化,代码也能正常工作。

那么......这里的交易是什么? 谢谢!

根据要求,整个程序的汇编输出:

使用-O2: clicky

使用-O3: clicky

我在GCC 4.6.2上观察到这种行为(与MinGW一起运行)

从我的评论:

确保编译器具有有关目标体系结构的正确信息。 从读取-O3输出看,编译器正在为您设置SIMD优化,它实际上通过使用向量指令(例如movdqa )使代码更加平行。 如果目标处理器与编译器发出代码的100%不匹配,则最终可能会出现非法指令。

我将此添加为Unwind答案的延伸(我接受它,因为它让我走上了正确的轨道)。

在筛选优化代码后,我注意到了AVX指令。 起初,考虑到我的处理器支持AVX指令集,我认为它不会引起问题。 然而,事实证明有两个不同的AVX版本:AVX1和AVX2。 而且,虽然我的处理器只支持AVX1,但只要处理器支持两个版本中的任何一个版本,gcc就会不加区分地使用AVX2操作码(llvm犯了同样的错误,有bug报告 )。 据我所知,这是错误的操作和编译器错误。

结果是AVX1系统上的AVX2代码,这显然会导致非法指令。 它解释了很多东西,从小于32字节输入的代码(由于256位寄存器宽度)到我的Linux机器上的代码,这恰好是CPU支持仅限于SSE3的虚拟机。

修复是要么禁用-O3又返回到-O2,其中gcc不会求助于最硬核的SIMD指令来优化简单代码,或者使用volatile关键字来强制它通过每个字节的缓冲区字节,辛苦地,像这样:

*(unsigned char volatile *)dst ^= *(unsigned char volatile *)src;

这当然非常慢,可能比仅使用-O2(忽略整个程序的反应)更糟糕,但它可以通过int而不是填充来通过缓冲区int来解决,这对于速度。

另一个很好的解决方法是升级到没有此bug的gcc版本(此版本可能尚不存在,我还没有检查过)。

编辑:最终修复是在GCC上抛出-mno-avx标志,从而禁用任何和所有AVX操作码,完全否定了没有代码修改的错误(并且一旦修补的编译器版本可用就可以轻松删除)。

多么糟糕的编译错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM