【问题标题】:Iterating and dereferencing unaligned pointer to memory causing segmentation fault ? Bug in GCC optimizer?迭代和取消引用指向内存的未对齐指针导致分段错误? GCC优化器中的错误?
【发布时间】:2021-08-13 12:06:08
【问题描述】:
// Compiled with GCC 7.3.0, x86-64 -g -O3 -std=gnu++11
// Tested on OS (1) Ubuntu 18.04 LTS, (2) Gentoo

int Listen(... socket)
{
    char buffer[INT16_MAX];
    . . .
    . . . = recvfrom(socket, buffer, ....)
    ParseMsg(buffer)
}

void ParseMsg(uint8_t *const msg)
{
    . . .
    uint16_t* word_arr = (uint16_t*)(msg+15); // if I changed 15 to 16 (aligned to uint16_t) 
                                              // the program doesn't crash

    for(size_t i = 0 ; i < 30 ; ++i)
    {
        word_arr[i] = 1; // after some iterations (around 13) the program crashes with segmentation fault
                         // if i add a print statement inside the loop the program doesn't crash
    }

    // word_arr[20] = 1; // if I assign value not in loop the program doesn't crash 
}

我找到了一些讨论这个问题的链接:
https://github.com/samtools/htslib/issues/400
https://github.com/xianyi/OpenBLAS/issues/1137
但他们用处理器术语说话。有人可以确认这个错误存在吗?

附言
我使用 -O2 优化标志运行代码。没有崩溃

【问题讨论】:

  • 您应该在调试器中查看失败的指令。很可能是向量指令。硬件是否通常接受该大小的未对齐读取并不重要,如果 C++ 标准规定未对齐读取是非法的,编译器可以使用该信息进行优化。
  • 这不是优化器中的错误,而是您的代码中的问题。根据 C++ 标准,未对齐访问具有未定义的行为。
  • 由于严格的别名规则,您的代码格式错误。请参阅最近的问题stackoverflow.com/a/67636420/12939557 和著名的问题stackoverflow.com/questions/98650/…
  • @JérômeRichard 这里有点复杂。字符指针(包括 signed charunsigned char)被明确排除在严格别名规则之外,并且在大多数实现中,uint8_t 是来自 unsigned char 的 typdef,因此不适用严格别名规则。
  • @Johan 确实!我对uint8_t 类型感到困惑。我的错。无论如何,解决此问题的解决方案看起来与类型双关问题相同:使用 memcpy(或 C++20 中的 bitcast,或 C 中的联合)。

标签: gcc optimization segmentation-fault compiler-optimization memory-alignment


【解决方案1】:

问题确实在 uint16_t 指针(应该是 2)的对齐下划线,结合 -O3 编译器正在尝试使用矢量化(SIMD)优化您的循环,因此尝试将未对齐的参数加载到SSE 注册。

这可以解释为什么它在以下情况下起作用:

  1. 您将偏移量从 15 更改为 16 - 导致 uint16_t 指针对齐
  2. 使用-O2 - 禁用矢量化
  3. 删除循环/在循环中添加打印 - 同时禁用矢量化

请参考以下链接,其中包含与您类似的问题和一些非常详细的答案:

c-undefined-behavior-strict-aliasing-rule-or-incorrect-alignment

【讨论】:

  • 矢量化优化确实是个问题!使用 -03 和 -fno-tree-vectorize(禁用矢量化)编译导致程序不崩溃
猜你喜欢
  • 2013-06-05
  • 2023-03-26
  • 1970-01-01
  • 2018-11-04
  • 2015-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-25
相关资源
最近更新 更多