Я пытаюсь понять, как работает выравнивание стека, как описано в что такое "выравнивание стека"? , но у меня возникают проблемы с получением небольшого примера для демонстрации указанного поведения. Я изучаю выделение стека моей функции foo:
void foo() {
int a = 0;
char b[16];
b[0] = 'a';
}
Я скомпилировал исходный файл с gcc -ggdb example.c -o example.out
(т.е. без каких-либо флагов компилятора), и дамп ассемблера из gdb читает:
(gdb) disassemble foo
Dump of assembler code for function foo:
0x08048394 <+0>: push %ebp
0x08048395 <+1>: mov %esp,%ebp
0x08048397 <+3>: sub $0x20,%esp
0x0804839a <+6>: movl $0x0,-0x4(%ebp)
0x080483a1 <+13>: movb $0x61,-0x14(%ebp)
0x080483a5 <+17>: leave
0x080483a6 <+18>: ret
End of assembler dump.
Мой стек выделен кусками по 16 байт (я проверял это с помощью нескольких других тестов). Согласно дампу ассемблера, здесь выделено 32 байта, потому что (16 <4 + 16 <32), однако я ожидал, что целое число «а» будет выделено в первых 16 байтах, а затем массив символов будет выделен в следующих 16 байтах. (оставляя пробел между 12 байтами). Но кажется, что и целому числу, и массиву символов был выделен непрерывный кусок в 20 байтов, что неэффективно в соответствии с обсуждением, которое я упоминал выше. Может кто-нибудь объяснить, что мне здесь не хватает? </p>
РЕДАКТИРОВАТЬ : я пришел к выводу, что мой стек выделяется кусками по 16 байт с помощью программы, подобной приведенной ниже:
void foo() {
char a[1];
}
и соответствующий ассемблерный дамп:
(gdb) disassemble foo
Dump of assembler code for function foo:
0x08048394 <+0>: push %ebp
0x08048395 <+1>: mov %esp,%ebp
0x08048397 <+3>: sub $0x10,%esp
0x0804839a <+6>: leave
0x0804839b <+7>: ret
End of assembler dump.
Вы можете видеть, что в стеке выделено 16 байт для символьного массива размером 1 (необходим только 1 байт). я могу увеличить размер массива до 16, и дамп ассемблера останется прежним, но когда он равен 17, он выделяет 32 байта в стеке. Я пробовал много таких образцов, и результат тот же; стековая память выделяется кусками по 16 байт. Подобная тема обсуждалась в Распределение стека, заполнение и выравнивание , но я больше всего хочу выяснить, почему выравнивание не имеет эффекта в моем примере.