c++ - x86、C++、gcc 和内存对齐

标签 c++ gcc x86-64 memory-alignment

我有这个简单的 C++ 代码:

int testFunction(int* input, long length) {
    int sum = 0;
    for (long i = 0; i < length; ++i) {
        sum += input[i];
    }
    return sum;
}


#include <stdlib.h>
#include <iostream>
using namespace std;
int main()
{
    union{
        int* input;
        char* cinput;
    };

    size_t length = 1024;
    input = new int[length];


    //cinput++;

    cout<<testFunction(input, length-1);

}

如果我用带有 -O3 的 g++ 4.9.2 编译它,它运行良好。我预计,如果我取消对倒数第二行的注释,它会运行得更慢,但它会因 SIGSEGV 而彻底崩溃。

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400754 in main ()
(gdb) disassemble 
Dump of assembler code for function main:
   0x00000000004006e0 <+0>:     sub    $0x8,%rsp
   0x00000000004006e4 <+4>:     movabs $0x100000000,%rdi
   0x00000000004006ee <+14>:    callq  0x400690 <_Znam@plt>
   0x00000000004006f3 <+19>:    lea    0x1(%rax),%rdx
   0x00000000004006f7 <+23>:    and    $0xf,%edx
   0x00000000004006fa <+26>:    shr    $0x2,%rdx
   0x00000000004006fe <+30>:    neg    %rdx
   0x0000000000400701 <+33>:    and    $0x3,%edx
   0x0000000000400704 <+36>:    je     0x4007cc <main+236>
   0x000000000040070a <+42>:    cmp    $0x1,%rdx
   0x000000000040070e <+46>:    mov    0x1(%rax),%esi
   0x0000000000400711 <+49>:    je     0x4007f1 <main+273>
   0x0000000000400717 <+55>:    add    0x5(%rax),%esi
   0x000000000040071a <+58>:    cmp    $0x3,%rdx
   0x000000000040071e <+62>:    jne    0x4007e1 <main+257>
   0x0000000000400724 <+68>:    add    0x9(%rax),%esi
   0x0000000000400727 <+71>:    mov    $0x3ffffffc,%r9d
   0x000000000040072d <+77>:    mov    $0x3,%edi
   0x0000000000400732 <+82>:    mov    $0x3fffffff,%r8d
   0x0000000000400738 <+88>:    sub    %rdx,%r8
   0x000000000040073b <+91>:    pxor   %xmm0,%xmm0
   0x000000000040073f <+95>:    lea    0x1(%rax,%rdx,4),%rcx
   0x0000000000400744 <+100>:   xor    %edx,%edx
   0x0000000000400746 <+102>:   nopw   %cs:0x0(%rax,%rax,1)
   0x0000000000400750 <+112>:   add    $0x1,%rdx
=> 0x0000000000400754 <+116>:   paddd  (%rcx),%xmm0
   0x0000000000400758 <+120>:   add    $0x10,%rcx
   0x000000000040075c <+124>:   cmp    $0xffffffe,%rdx
   0x0000000000400763 <+131>:   jbe    0x400750 <main+112>
   0x0000000000400765 <+133>:   movdqa %xmm0,%xmm1
   0x0000000000400769 <+137>:   lea    -0x3ffffffc(%r9),%rcx
---Type <return> to continue, or q <return> to quit---

为什么会崩溃?这是编译器错误吗?我是否导致了一些未定义的行为?编译器是否期望 int 总是 4 字节对齐?

我也在 clang 上测试过,没有崩溃。

这是 g++ 的汇编输出:http://pastebin.com/CJdCDCs4

最佳答案

代码input = new int[length]; cinput++; 导致未定义的行为,因为第二条语句正在从一个不活跃的 union 成员中读取。

即使忽略它,testFunction(input, length-1) 也会出于同样的原因再次出现未定义的行为。

即使忽略这一点,求和循环也会通过错误类型的左值访问对象,这具有未定义的行为。

即使忽略这一点,从未初始化的对象中读取数据(就像求和循环所做的那样)也会再次出现未定义的行为。

关于c++ - x86、C++、gcc 和内存对齐,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27150878/

相关文章:

使用 -fprofile-generate 时的 gcc 宏

c++ - 析构函数抛出异常

c++ - 如果我不将它存储在任何地方,返回值会怎样?

c++ - 是否可以从较晚的模板参数推断或默认较早的模板参数?

c++ - g++ (MinGW)、C++11 和 SSE

c++ - c/c++ 编译器是否通过二次幂值将常量除法优化为移位?

linux - 简单乘法函数中的推送/弹出段错误

assembly - 打印有符号整数优化

loops - 如何增加寄存器中的每个字节? (64位,Linux,NASM)

c++ - 为什么 std::same_as 以如此奇怪的方式实现?