迭代和取消引用指向内存的未对齐指针会导致分段错误吗?GCC优化器中的错误? //使用GCC 7.3.0编译,x86-64-g-O3-std=gnu++11 //在操作系统上测试(1)Ubuntu 18.04 LTS,(2)Gentoo int侦听(…套接字) { 字符缓冲区[INT16_MAX]; . . . …=recvfrom(套接字、缓冲区等) ParseMsg(缓冲区) } void ParseMsg(uint8_t*const msg) { . . . uint16_t*word_arr=(uint16_t*)(msg+15);//如果我将15更改为16(与uint16_t对齐) //程序没有崩溃 对于(尺寸i=0;i

迭代和取消引用指向内存的未对齐指针会导致分段错误吗?GCC优化器中的错误? //使用GCC 7.3.0编译,x86-64-g-O3-std=gnu++11 //在操作系统上测试(1)Ubuntu 18.04 LTS,(2)Gentoo int侦听(…套接字) { 字符缓冲区[INT16_MAX]; . . . …=recvfrom(套接字、缓冲区等) ParseMsg(缓冲区) } void ParseMsg(uint8_t*const msg) { . . . uint16_t*word_arr=(uint16_t*)(msg+15);//如果我将15更改为16(与uint16_t对齐) //程序没有崩溃 对于(尺寸i=0;i,gcc,optimization,segmentation-fault,compiler-optimization,memory-alignment,Gcc,Optimization,Segmentation Fault,Compiler Optimization,Memory Alignment,我找到了一些关于这个问题的链接: 但他们用处理器术语说话。有人能确认这个错误存在吗 p、 s 我使用-O2优化标志运行代码。未崩溃该问题在对齐uint16_t指针(应为2)时强调,与-O3相结合,编译器正在尝试使用向量化(SIMD)优化循环,因此尝试将未对齐的参数加载到SSE寄存器 这可以解释为什么它在以下情况下工作: 将偏移量从15更改为16-使uint16\t指针对齐 使用-O2-禁用矢量化 删除循环/在循环中添加打印-同时禁用矢量化 请参考以下链接,其中有一个与您的问题类似的问题和一些

我找到了一些关于这个问题的链接:


但他们用处理器术语说话。有人能确认这个错误存在吗

p、 s

我使用-O2优化标志运行代码。未崩溃

该问题在对齐
uint16_t
指针(应为2)时强调,与
-O3
相结合,编译器正在尝试使用向量化(SIMD)优化循环,因此尝试将未对齐的参数加载到SSE寄存器

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

  • 将偏移量从15更改为16-使
    uint16\t
    指针对齐
  • 使用
    -O2
    -禁用矢量化
  • 删除循环/在循环中添加打印-同时禁用矢量化
  • 请参考以下链接,其中有一个与您的问题类似的问题和一些非常详细的答案:


    您应该在调试器中查找失败的指令。很可能是矢量指令。如果硬件通常接受不对齐的大小的读取,这并不重要,如果C++标准说未对齐的读取是非法的,编译器可以使用这些信息来优化。这不是优化器中的一个缺陷,这是代码中的问题。根据C++标准,未对齐的访问具有未定义的行为。由于严格的混叠规则,代码不正确。看看最近的问题和著名的问题。@JérômeRichard这里有点复杂。字符指针(包括
    signed Char
    unsigned Char
    )被明确排除在严格别名规则之外,并且在大多数实现中
    uint8\u t
    unsigned Char
    的一个类型定义,因此严格别名规则不适用。@Johan确实!我对类型
    uint8\u t
    感到困惑。我的错。无论如何,解决此问题的方法与类型双关问题的方法相同:在C++20中使用
    memcpy
    (或
    bitcast
    ,或在C中使用UNION)。矢量化优化似乎就是问题所在!使用-03和-fno-tree-vectorize(禁用向量化)编译导致程序没有崩溃