Подтвердить что ты не робот

Если глобальная переменная инициализируется до 0, перейдет ли она в BSS?

Все инициализированные глобальные/статические переменные перейдут в раздел инициализированных данных. Все неинициализированные глобальные/статические переменные перейдут в раздел неинициализированных данных (BSS). Переменные в BSS получат значение 0 во время загрузки программы.

Если глобальная переменная явно инициализируется нулем (int myglobal = 0), где эта переменная будет сохранена?

4b9b3361

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