Почему в стеке между локальными переменными моей функции есть пространство памяти? - PullRequest
0 голосов
/ 31 января 2019

У меня есть программа на C, скомпилированная с gcc на Ubuntu x86.Это функция, которую я вызываю с main

void addme()
{
  long a = 5;
  char c = '3';
  long array[3];
  array[0] = 2;
  array[1] = 4;
  array[2] = 8;
}

Если я прерваюсь на последней строке и отлаживаю / проверяю, это то, что я получаю

(gdb) print &a
$5 = (long *) 0xbffff04c
(gdb) print &c
$6 = 0xbffff04b "3\005"
(gdb) print &array
$7 = (long (*)[3]) 0xbffff03c
(gdb) x 0xbffff03c
0xbffff03c:     0x00000002
(gdb) x 0xbffff040
0xbffff040:     0x00000004
(gdb) x 0xbffff044
0xbffff044:     0x00000008
(gdb) x 0xbffff04c
0xbffff04c:     0x00000005

Почему 0xbffff048, 0xbffff049, 0xbffff04a и 0xbffff04b зарезервированы для символа c, когда для хранения символа требуется только 0xbffff04b?

Кроме того, что означает это обозначение "3\005"?

С другой стороны, если мой методкак показано ниже, для символа с тремя дополнительными байтами памяти заполнение отсутствует

void addme()
{
  long a = 5;
  char c = '3';
  char line[9];
  char d = '4';
}

Так выглядит распределение памяти для этих переменных (пропуская ведущую часть адреса)

a - f04c 
c - f04b 
d - f04a 
line - f041, f042, f043, f044, f045, f046, f047, f048, f049

Также не уверен, почему d был поднят выше line в резервировании памяти.Я предполагаю, потому что это не было инициализировано, это идет в другую область в стеке чем инициализированные переменные?

1 Ответ

0 голосов
/ 31 января 2019

Это называется выравнивание .Объекты выровнены по кратным числам определенных целых чисел (обычно 4 или 8 в случае long) для быстрого доступа.В общем, вам не нужно слишком беспокоиться о размещении в C ++, поскольку спецификация языка обычно позволяет компилятору выбирать наиболее эффективный (с точки зрения вашей ориентации оптимизации) способ хранения объектов, что обычно имеет место.

Каждый тип объекта имеет свойство с именем требование выравнивания , которое представляет собой целочисленное значение (типа std::size_t, всегда степень 2), представляющее числобайты между последовательными адресами, по которым могут быть размещены объекты этого типа.Требование выравнивания типа можно запросить с помощью alignof или std::alignment_of.Функция выравнивания указателя std::align может использоваться для получения соответствующим образом выровненного указателя в некотором буфере, а std::aligned_storage может использоваться для получения надлежащим образом выровненного хранилища.

Каждый тип объекта накладывает свое требование выравнивания на каждый объект этого типа;Более строгое выравнивание (с большим требованием выравнивания) может быть запрошено с использованием alignas.

. Чтобы удовлетворить требования выравнивания всех нестатических членов класса, padding может быть вставлено после некоторогоего членов.

( cppreference )


Относительно вашего второго вопроса @ prl дает ответ:

Поскольку c - это char, &c - это char *, поэтому GDB печатает его как строку.Первый символ строки - «3», значение c.Следующий символ - 5, младший байт a, который GDB печатает в восьмеричной записи escape. Escape-последовательности в C в Википедии - prl 1024 мин. Назад


Почему пэд исчезает, когда вы объявляете char s после char?Потому что в этом случае выравнивание char выглядит равным 1, что означает, что заполнение не требуется.С другой стороны, long кажется равным 4, поэтому должен быть 4-байтовый пробел, в котором помещается char.

Я полагаю, потому что это не былоt инициализируется, он идет в другую область в стеке, чем инициализированные переменные?

Не совсем.То, является ли переменная инициализированной (в общем случае), не влияет на ее размещение, только на то, что она имеет неопределенное значение.С другой стороны, компилятор может свободно размещать объекты в памяти так, как ему нравится.На практике компиляторы «наслаждаются» реализациями, которые приводят к эффективности как в памяти, так и во времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...