Если глобальная переменная инициализируется в 0, пойдет ли она в BSS?
Все инициализированные глобальные / статические переменные перейдут в раздел инициализированных данных. Все неинициализированные глобальные / статические переменные перейдут в раздел неинициализированных данных(BSS). Переменные в BSS получат значение 0 во время загрузки программы.
Если глобальная переменная явно инициализируется нулем (int myglobal = 0
), где будет храниться эта переменная?
3 ответа
Компилятор может поместить такую переменную в bss
а также в data
, Например, GCC имеет специальную опцию, контролирующую такое поведение:
-fno-zero-initialized-in-bss
Если цель поддерживает раздел BSS, GCC по умолчанию помещает переменные, которые инициализируются в ноль, в BSS. Это может сэкономить место в результирующем коде. Эта опция отключает это поведение, потому что некоторые программы явно полагаются на переменные, идущие в раздел данных. Например, чтобы итоговый исполняемый файл мог найти начало этого раздела и / или сделать предположения на основании этого.
По умолчанию
-fzero-initialized-in-bss
,
Пробовал со следующим примером (test.c
файл):
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
Достаточно просто проверить конкретный компилятор:
$ 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)
,
Поведение зависит от реализации Си. Он может заканчиваться либо в.data, либо в.bss, и для увеличения изменений, которые не заканчиваются в.data, занимая избыточное пространство, лучше не инициализировать его явно в 0, так как он все равно будет установлен в 0, если объект имеет статическую длительность.