2009-08-11 4 views
8

У меня возникла небольшая проблема при обучении. Я знаю, что неинициализированные глобальные переменные в C назначаются секции .bss в исполняемом файле ELF. Но что с ними происходит, когда я начну их использовать? I.e. они получают место в куче или где-то еще?Где неинициализированные глобальные переменные идут после инициализации?

Я попытался выяснить, напечатав адрес (еще неинициализированного) глобальной переменной с

printf("%x",&glbl); 

, который всегда возвращает то же значение 0x80495bc ... Почему?

+1

Я заметил, что вы ответили через 5 минут после того, как задали вопрос. Вы получите больше ответов, если оставите его открытым в течение некоторого времени, поскольку люди будут более мотивированы, чтобы улучшить ответы. – Adriaan

+0

Спасибо за подсказку, я обязательно сделаю это в следующий раз. – Patrick

ответ

8

Когда ОС загружает вашу программу, она выделяет достаточное количество памяти из адресного пространства вашей программы, чтобы хранить все в разделе .bss и нули всей этой памяти. Когда вы назначаете или читаете или принимаете адрес переменной, вы управляете этой памятью, которая была выделена для обеспечения хранения для секции .bss.

+0

Ах, и это также объясняет, почему значение, содержащееся в неинициализированной глобальной переменной, всегда было нулевым. Благодаря! – Patrick

+0

Некоторые компиляторы/архитектуры поддерживают раздел SBSS для небольших данных. Это часто делается как оптимизация, так что данные могут быть получены путем индексирования с начала раздела SBSS. Это часто можно сделать, используя регистр gp и 16-битную индексацию – zebrabox

2

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

1

BSS является заполнителем, определенным в вашем исполняемом (или ELF) формате. Таким образом, он не занимает дисковое пространство, но указывает только, какую область памяти следует назначать компоновщику или загрузчику.

Точная операция зависит от операционной системы. Поскольку вы ссылаетесь на ELF, я предполагаю, что он предназначен для использования во встроенной системе. Если вы создадите для ROMmable кода, ваш cmd-файл компоновщика сопоставляет BSS с областью статического адреса.

В случае, если вы создаете для операционной системы (то есть Linux), загрузчик из операционной системы выполнит пропуск перемещения, в котором он сопоставляет все местоположения, помеченные как относительные в формате excecutable, в физические или логические местоположения в памяти.

Поскольку вы указываете, что всегда видите одно и то же значение, это означает, что процесс повторяется для вашей системы. Ожидайте увидеть изменения при смене файлов-линкеров (т. Е. Областей адресов), порядок ссылок (т. Е. Модули получат назначенное пространство в другом порядке) или операционной системы.

Удерживайте или не используете значения BSS, адрес останется неизменным для запуска процесса.

1

Эта секция BSS получает блок памяти в адресном пространстве процесса, как и разделы кода и стека (и любые другие ELF могут иметь). Когда-то там они не идут куда угодно. Затем загрузчик упорядочивает объекты, а затем вызывает точку входа в процесс.

Смежные вопросы