Если глобальная переменная инициализируется в 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, если объект имеет статическую длительность.

Другие вопросы по тегам