Если глобальная переменная инициализируется до 0, перейдет ли она в BSS?
Все инициализированные глобальные/статические переменные перейдут в раздел инициализированных данных.
Все неинициализированные глобальные/статические переменные перейдут в раздел неинициализированных данных (BSS). Переменные в BSS получат значение 0 во время загрузки программы.
Если глобальная переменная явно инициализируется нулем (int myglobal = 0
), где эта переменная будет сохранена?
Ответы
Ответ 1
Компилятор может поместить такую переменную в bss
, а также в data
. Например, GCC имеет специальную опцию, контролирующую такое поведение:
-fno-zero-initialized-in-bss
Если цель поддерживает раздел BSS, GCC по умолчанию ставит переменные, которые инициализируются нулем в BSS. Эта может сэкономить место в полученном коде. Эта опция отключает эту потому что некоторые программы явно полагаются на переменные, идущие в раздел данных. Например, чтобы полученный исполняемый файл мог найти начало этого раздела и/или сделать предположения на основе этого.
По умолчанию используется -fzero-initialized-in-bss
.
Пробовал следующий пример (test.c
file):
int put_me_somewhere = 0;
int main(int argc, char* argv[]) { return 0; }
Компиляция без параметров (неявно -fzero-initialized-in-bss
):
$ touch test.c && make test && objdump -x test | grep put_me_somewhere
cc test.c -o test
0000000000601028 g O .bss 0000000000000004 put_me_somewhere
Компиляция с опцией -fno-zero-initialized-in-bss
:
$ touch test.c && make test CFLAGS=-fno-zero-initialized-in-bss && objdump -x test | grep put_me_somewhere
cc -fno-zero-initialized-in-bss test.c -o test
0000000000601018 g O .data 0000000000000004 put_me_somewhere
Ответ 2
Достаточно легко проверить конкретный компилятор:
$ cat bss.c
int global_no_value;
int global_initialized = 0;
int main(int argc, char* argv[]) {
return 0;
}
$ make bss
cc bss.c -o bss
$ readelf -s bss | grep global_
32: 0000000000400420 0 FUNC LOCAL DEFAULT 13 __do_global_dtors_aux
40: 0000000000400570 0 FUNC LOCAL DEFAULT 13 __do_global_ctors_aux
55: 0000000000601028 4 OBJECT GLOBAL DEFAULT 25 global_initialized
60: 000000000060102c 4 OBJECT GLOBAL DEFAULT 25 global_no_value
Мы ищем местоположение 0000000000601028
и 000000000060102c
:
$ readelf -S bss
There are 30 section headers, starting at offset 0x1170:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
...
[24] .data PROGBITS 0000000000601008 00001008
0000000000000010 0000000000000000 WA 0 0 8
[25] .bss NOBITS 0000000000601018 00001018
0000000000000018 0000000000000000 WA 0 0 8
Похоже, что оба значения хранятся в разделе .bss
в моей системе: gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4)
.
Ответ 3
Поведение зависит от реализации C. Это может закончиться либо .data, либо .bss, и для увеличения изменений, которые он не попадает в .data с избыточным пространством вверх, лучше не явно инициализировать его до 0, так как он будет равен 0 в любом случае, если объект имеет статическую продолжительность.