Понимание распределения и выравнивания стека - PullRequest
7 голосов
/ 27 января 2011

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

Ответы [ 5 ]

6 голосов
/ 27 января 2011

Я думаю, что вам не хватает того факта, что не требуется, чтобы все переменные стека были индивидуально выровнены по 16-байтовым границам.

0 голосов
/ 17 декабря 2011

Вы можете проверить, как выделяется дополнительная память для вашей структуры данных, с помощью инструмента под названием pahole http://packages.debian.org/lenny/dwarves. Он показывает вам все дыры в вашей программе: размер ваших данных, если вы их суммируете, и реальный размер, выделенный для вашей застрявшей

0 голосов
/ 27 января 2011

Хороший пример - увидеть это на структуре.

struct a{
    int a;
    char b;
    int c;
} a;

В 32-битной системе это будет 4 + 1 + 4 байта, если брать отдельно.

Поскольку структура и ее члены выровнены, "char b" будет 4 байта, что приведет к 12 байтам.

struct b{
    int a;
    char b;
    int c;
} __attribute__((__packed__)) b;

Используя упакованный атрибут, вы можете заставить его сохранять минимальный размер. Таким образом, эта структура составляет 9 байтов.

Вы также можете проверить это http://sig9.com/articles/gcc-packed-structures

Надеюсь, это поможет.

0 голосов
/ 27 января 2011

Я никогда не слышал о такой вещи, как конкретное выравнивание стека.Если для ЦП существуют требования к выравниванию, то выравнивание выполняется для всех типов памяти данных, независимо от того, хранится она в стеке или где-либо еще.Он начинается с четных адресов с 16, 32 или 64-битными данными, следующие.

16 байт может быть своего рода оптимизацией кэш-памяти на кристалле, хотя мне это кажется немного надуманным.

0 голосов
/ 27 января 2011

Обычное правило - переменные размещаются на 32-битных границах.Я не уверен, почему вы думаете, что 16 байтов имеют какое-то особое значение.

...