Действительно странная причудливость GCC.Проверьте это:
main() { int a[100]; a[0]=1; }
производит эту сборку:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 81 ec 18 01 00 00 sub $0x118,%rsp
b: c7 85 70 fe ff ff 01 movl $0x1,-0x190(%rbp)
12: 00 00 00
15: c9 leaveq
16: c3 retq
Вершина стека явно 400, так как это массив 100 * 4.Поэтому, когда он пишет в первую запись, он делает rbp-400 (строка 'b').Хорошо.Но почему он вычитает 280 из стекового (строка '4') указателя?Разве это не указывает на середину массива?
Если мы добавим вызов функции позже, gcc сделает правильную вещь:
b() {}
main() { int a[100]; a[0]=1; b(); }
создает эту сборку:
0000000000000000 <b>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: c9 leaveq
5: c3 retq
0000000000000006 <main>:
6: 55 push %rbp
7: 48 89 e5 mov %rsp,%rbp
a: 48 81 ec 90 01 00 00 sub $0x190,%rsp
11: c7 85 70 fe ff ff 01 movl $0x1,-0x190(%rbp)
18: 00 00 00
1b: b8 00 00 00 00 mov $0x0,%eax
20: e8 00 00 00 00 callq 25 <main+0x1f>
25: c9 leaveq
26: c3 retq
Здесь он правильно вычитает 400 (строка 'a').
Почему происходит изменение при добавлении вызова функции?GCC просто ленив и не делает это правильно, потому что это не имеет значения?Что происходит?Очевидно, это происходит только при компиляции для x86_64, но не для простого x86.Это как-то странно связано с "redzone" в x86_64?Что именно происходит?