Почему между переменными, которые я инициировал в стеке, существует «разрыв»? - PullRequest
0 голосов
/ 30 января 2020

enter image description here

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char **argv) {
    int modified;
    char buffer[64];

    modified = 0;
    gets(buffer);

    if(modified != 0)
        printf("Changed!");
    else
        printf("Not changed!");
}

Я пытаюсь поиграть с переполнением буфера.

Когда счетчик программы достигает if ( изменено! = 0) , базовый указатель равен 0x00007fffffffdfe0.

Прямо под базовым указателем я вижу 4 байта, которые содержат целое число 0, что имеет смысл.

Однако буфер не прямо под измененным int.

Похоже, что 4 байта по 0 затем 0x00007fff находятся в стеке, затем 64 байта As, которые я ввел, следуют после.

Почему нет буфера символов [ 64] приходят сразу после изменения int? почему есть «пробел»?

Я скомпилировал его с помощью g cc -g -fno-stack-protector test1. c -o test1

Спасибо

Ответы [ 2 ]

4 голосов
/ 30 января 2020

Во-первых, вы должны понимать, что компилятор / компоновщик может назначать любой адрес переменным, которые вы объявляете в области действия 'automati c' (то есть локально для функции - и main на самом деле это просто еще одна функция).

Относительно того, «почему» присутствуют 4 байта нулей - это почти наверняка потому, что на используемой платформе компилятор знает, что доступ к памяти более эффективен (то есть быстрее), когда адрес этой памяти выровнен по значению восемь байт - поэтому он «добавляет» дополнительные четыре байта, чтобы соответствующим образом «выровнять» адрес вашего массива buffer , См. здесь для обсуждения выравнивания и эффективности.

3 голосов
/ 30 января 2020

У вас уже есть общий ответ. Специально для вашей платформы (GCC / Linux / x86_64) соответствующий ABI (System V x86-64) указывает, что массивы размером 16 байтов или больше всегда выровнены как минимум на 16 байтов. Это, как пояснил @AdrianMole в своем ответе, предназначено для повышения производительности, в частности, для разрешения использования инструкций SSE для массива.

См. Стр. 15 в System v x86-64 psABI версии 1.0, связанный здесь .

Если вы сделаете размер массива меньше 16 байт, этого не произойдет. Однако была также ошибка G CC, которая случайно применяла это правило ко всем массивам размером более 16 бит, т.е. 2 байта. Это было исправлено с помощью G CC 7.1.

...