Понимание распределения и выравнивания стека

Я пытаюсь понять, как работает выравнивание стека, как описано в , что такое «выравнивание стека»? , но у меня проблемы с получением небольшого примера, демонстрирующего указанное поведение . Я исследую распределение стека моей функции 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

РЕДАКТИРОВАТЬ : Я пришел к выводу, что мой стек выделяется кусками по 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 байт. Похожая тема обсуждалась в Распределение, заполнение и выравнивание стека , но мне больше интересно узнать, почему выравнивание не действует в моем примере.

7
задан Community 23 May 2017 в 12:34
поделиться