Где инициализированные авто переменные (локальные переменные) помещаются в объектный файл? - PullRequest
0 голосов
/ 10 июня 2019

Как и инициализированные данные глобальных переменных помещаются в раздел .data, а унифицированные глобальные переменные находятся в разделе .bss, в какой раздел объектного файла компилятор помещает инициализированные данные авто переменных (локальных переменных)?

Ответы [ 3 ]

2 голосов
/ 10 июня 2019

Объект автоматической продолжительности хранения, такой как int x, определенный внутри функции, , в общем, не может быть сохранен в объектном файле.Это связано с тем, что функция может вызываться рекурсивно (прямо или косвенно) любое количество раз, и для каждого такого вызова должен существовать другой экземпляр объекта и, следовательно, одно место в объектном файле (позволяющее эту часть объектного файла).может отображаться в памяти в том или ином смысле во время выполнения программы) не может служить памятью для объекта.

В определенных обстоятельствах возможно, что одна копия данных в объектном модуле будет служить объектом автоматическогопродолжительность хранения, например, когда компилятор может определить, что функция не вызывается рекурсивно, и, следовательно, одновременно может существовать только один экземпляр объекта.

Однако, чтобы реализовать инициализированный объект, компилятор долженпредусмотреть для установки объекта его начальное значение.Фактический объект, используемый во время выполнения программы, может находиться в стеке или в регистре, но компилятор должен установить его начальное значение.Для некоторых начальных значений, таких как нулевые или малые константы, компилятор может создавать начальное значение «на лету» во время выполнения программы, возможно, используя непосредственные операнды в инструкциях.(В этом случае начальное значение эффективно сохраняется в разделе кода объектного модуля.) Для констант, которые нелегко построить на лету, компилятор может сохранить значение в виде данных в объектном модуле, обычно в режиме чтения.только (постоянный) раздел данных.Конечно, поскольку эти данные предназначены для внутреннего использования компилятором (это то, что компилятор сохраняет для использования для начального значения; это не сам объект), они не будут помечены именем объекта.Компилятор идентифицирует его по внутреннему имени или числовому смещению от некоторого местоположения.

Кроме того, объекты автоматического хранения могут быть инициализированы с непостоянными значениями.Они, конечно, вообще не хранятся в объектном модуле;они вычисляются во время выполнения программы.

Все вышеперечисленное подлежит модификации с помощью оптимизации и правила «как будто» стандарта C - автоматический объект может вообще не существовать в памяти программы во время выполнения, есликомпилятор может получить то же требуемое наблюдаемое поведение другими способами, такими как сведение использования объекта в другие вычисления.

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

2 голосов
/ 10 июня 2019

Автоматические переменные не имеют (и не могут) иметь местоположение, назначенное в объектном файле, потому что они существуют в одном экземпляре для каждого действующего экземпляра области блока, в которой они объявлены, а не в одном экземпляре, как статические объекты хранения.,Если они инициализированы, они должны быть инициализированы для каждого экземпляра функции, и компилятор может свободно генерировать любой код, который ему нравится, для установки их начальных значений.Когда значения являются константными выражениями, это может быть выполнено как memcpy из раздела в образе программы (таким образом, существует в объектном / исполняемом файле), но оно может и обычно включает только непосредственные операндывстроенный в исполняемый код.

0 голосов
/ 10 июня 2019

Это зависит.Обычно локальная декларация, такая как int x = 1;, присваивается регистру и компилируется в инструкцию для загрузки константы 1 в этот регистр.Реже место в памяти будет выделяться в стеке, и значение будет храниться там.

Любая переменная может быть полностью оптимизирована, если компилятор (считает это) может доказать, что рефакторинг программы осуществляется таким образом.не изменит свое наблюдаемое поведение.Например, если вы пишете static const int ok = 0;, то когда вы пишете x = ok;, любой здравомыслящий компилятор просто установит x на постоянную 0.

Если вы берете адрес локальной переменной и разыменовываете его, компилятор должен поместить переменную в какую-то ячейку памяти.Константа, известная во время компиляции, может храниться в постоянной памяти текстового сегмента.Статическая локальная переменная обычно хранится с другими статическими переменными в сегменте данных.В противном случае он будет помещен в стек.

В более сложном случае, например

double matrix[4][3] = { { 1,  0,  0, -1 },
                        { 0,  1, -1,  0 },
                        { 9,  0,  0,  1 } };

Обычно вы видите начальные значения, хранящиеся в статическом массиве, а затем копируемые в память.расположение в стеке или в векторные регистры, если компилятор может векторизовать ваш алгоритм.Другими словами, это как если бы вы объявили начальные значения как локальный массив static const, а затем скопировали их в рабочую копию.

Может показаться полезным поучаствовать в тестировании нескольких вариантов программы, таких как GodBolt .

double f (const double x)
{
  double matrix[2][2] = { {1, 0},
                          {0, 1} };

  double* const begin = &matrix[0][0];
  const double* const end =
    begin + sizeof(matrix)/sizeof(matrix[0][0]);

  for ( double* p = begin; p < end; ++p ) {
    *p *= x;
  }

  return (matrix[0][0] * matrix[1][1]) -
         (matrix[0][1] * matrix[1][0]);
}

Компиляторы сильно различаются по тому, какой код они генерируют.GCC оптимизирует цикл и все переменные, кроме начальных значений массива, который он хранит в статической памяти по адресу .LC0 и копирует в регистры.Clang генерирует несколько векторных инструкций, которые, кроме регистров, вообще не выделяют память.Теоретически, хороший статический анализатор может оптимизировать эту функцию до return x*x;.

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