[c] Почему нужен сегмент .bss?



Answers

Сегмент .bss - это оптимизация. Весь сегмент .bss описывается одним числом, возможно 4 байта или 8 байтов, которое дает его размер в текущем процессе, тогда как раздел .data имеет размер, .data сумме размеров инициализированных переменных. Таким образом, .bss делает исполняемые файлы меньше и быстрее загружается. В противном случае переменные могут находиться в сегменте .data с явной инициализацией до нулей; программе было бы трудно сказать разницу. (Подробно, адрес объектов в .bss , вероятно, будет отличаться от адреса, если он был в сегменте .data .)

В первой программе a будет в сегменте .data а b будет в сегменте .bss исполняемого файла. После загрузки программы различие становится несущественным. Во время выполнения b занимает 20 * sizeof(int) байтов.

Во второй программе var выделяется пространство, а назначение в main() изменяет это пространство. Так получилось, что пространство для var было описано в сегменте .bss а не в сегменте .data , но это не влияет на поведение программы при запуске.

Question

Я знаю, что глобальные и статические переменные хранятся в сегменте .data , а неинициализированные данные находятся в сегменте .bss . Я не понимаю, почему у нас есть выделенный сегмент для неинициализированных переменных? Если неинициализированная переменная имеет значение, назначенное во время выполнения, существует ли переменная все еще в сегменте .bss ?

В следующей программе a находится в сегменте .data , а b - в сегменте .bss ; это верно? Пожалуйста, поправьте меня, если мое понимание ошибочно.

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

int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
int b[20]; /* Uninitialized, so in the .bss and will not occupy space for 20 * sizeof (int) */

int main ()
{
   ;
}  

Кроме того, рассмотрите следующую программу,

#include <stdio.h>
#include <stdlib.h>
int var[10];  /* Uninitialized so in .bss */
int main ()
{
   var[0] = 20  /* **Initialized, where this 'var' will be ?** */
}



Система V ABI 4.1 (1997) (спецификация AKA ELF) также содержит ответ:

.bss этом разделе содержатся неинициализированные данные, которые вносят вклад в образ памяти программы. По определению система инициализирует данные нулями при запуске программы. Раздел не занимает файлового пространства, как указано типом раздела, SHT_NOBITS .

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

Недостатком, конечно же, является то, что все байты должны быть установлены в 0 когда ОС помещает их в память, что является более ограничительным, но является обычным прецедентом и отлично работает для неинициализированных переменных.

SHT_NOBITS типа раздела SHT_NOBITS повторяет это утверждение:

sh_size Этот член дает размер раздела в байтах. Если тип SHT_NOBITS , секция занимает sh_size байты в файле. Раздел типа SHT_NOBITS может иметь ненулевой размер, но он не занимает места в файле.

В стандарте C ничего не говорится о разделах, но мы можем легко проверить, где переменная хранится в Linux с objdump и readelf , и заключить, что неинициализированные глобальные readelf фактически хранятся в .bss , см., Например, такой ответ: https://.com/a/36725211/895245




Начиная с языка сборки Step-by-Step: программирование с помощью Linux Джеффом Дантеманом относительно раздела .data :

Раздел .data содержит определения данных инициализированных элементов данных. Инициализированные данные - это данные, которые имеют значение перед запуском программы. Эти значения являются частью исполняемого файла. Они загружаются в память, когда исполняемый файл загружается в память для выполнения.

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

и раздел .bss :

Не все элементы данных должны иметь значения перед запуском программы. Например, когда вы читаете данные из файла диска, вам нужно иметь место для того, чтобы данные шли после того, как они вошли с диска. Такие буферы данных определены в разделе .bss вашей программы. Вы выделяете некоторое количество байтов для буфера и присваиваете буферу имя, но вы не говорите, какие значения должны присутствовать в буфере.

Существует важная разница между элементами данных, определенными в разделе .data, и элементами данных, определенными в разделе .bss: элементы данных в разделе .data добавляют размер вашего исполняемого файла. Элементы данных в разделе .bss нет. Буфер, который занимает до 16 000 байт (или более, иногда намного больше), может быть определен в .bss и почти ничего (около 50 байтов для описания) не будет добавлен к размеру исполняемого файла.




Related