Проблемы размещения памяти в C (64-разрядная версия)

Я хотел понять, как работает программа "С" и хранить данные в машине. Итак, я посмотрел на Memory Layout C отсюда и следовал тем же инструкциям на моей машине, которая является 64-битной.

Первый раз, когда я написал программу (main имеет только return 0;) и использовал size Команда для исполняемого файла: она показала большую разницу как в текстовом, так и в сегменте данных.

text    data    bss     dec     hex     filename
10648   2400    2640    15688   3d48    33.exe

Но на упомянутом выше сайте это показало:

text    data    bss     dec     hex     filename
960     248     8       1216    4c0     memory-layout

Первый вопрос: Какие факторы (аппаратное / программное обеспечение) отвечают за распределение памяти? И что dec в макете ссылаетесь? /Вопрос заканчивается здесь

Но сначала я проигнорировал это и начал объявлять переменные (глобальные и статические), чтобы увидеть, где они хранятся. И я столкнулся с проблемой на этом этапе.

для этого кода:

#include <stdio.h> 
int global;  
int main(void) {
    //static int x;
    return 0; 
} 

Я получил вывод как:

text    data    bss     dec     hex     filename
10648   2400    2656    15704   3d48    33.exe

Это потому, что я объявил (неинициализирован) глобальную переменную, и именно поэтому 16 байтов (int-64bit) блока памяти было добавлено к bss так стало 2656 с 2640 (первый пример) я это понимаю.

Q2: Но когда я добавляю static int x это не добавление блока памяти в bss больше. Это ожидается?

text    data    bss     dec     hex     filename
10648   2400    2656    15704   3d48    33.exe 

Q3: И, наконец, когда я инициализирую глобальную переменную с 20, data был увеличен (ожидается) и dec также получил увеличение почему?

text    data    bss     dec     hex     filename
10648   2416    2656    15720   3d48    33.exe

Я знаю, что задавал много вопросов здесь, но я хотел точно знать, как это управление памятью работает в C.

Аригато:)

2 ответа

Решение

Какие факторы (аппаратное / программное обеспечение) отвечают за распределение памяти? И что означает дек в макете

Ваша программа делится на множество разделов при запуске. stack содержит локальные переменные. bss data содержит неинициализированные глобальные переменные. initialized data содержит инициализированные глобальные переменные. text содержит ваш текст (код).dec это сумма text, bss, data

Но когда я добавляю static int x, он больше не добавляет блок памяти в bss. Ожидается ли это?

Держите это неинициализированным, тогда это добавит.

Перед добавлением статической переменной:

   text    data     bss     dec     hex filename
   1099     544       8    1651     673 a.out

После добавления статической переменной:

   text    data     bss     dec     hex filename
   1099     544      16    1659     67b a.out

И, наконец, когда я инициализирую глобальную переменную с 20, данные были увеличены (ожидаемый), и dec также увеличился. Зачем?

Так как dec это сумма text, data, bss

Вот краткое резюме:

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

  • глобальные инициализируемые модифицируемые объекты и локальные инициализированные объекты, объявленные с static хранилище загружается в сегмент данных.

  • неинициализированные модифицируемые глобальные объекты и неинициализированные локальные static объекты размещаются в сегменте bss, которого нет в исполняемом файле.

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

  • В столбце dec указан общий размер программного кода и данных: сумма текста, данных и bss. Это не включает память, выделенную во время запуска, пространство стека и данные, выделяемые динамически из кучи или с использованием других специфических для ОС методов.

  • hex - шестнадцатеричное представление dec.

Эти значения варьируются в зависимости от операционной системы, компилятора, настроек компилятора и библиотек. На веб-сайте показаны выходные данные системы, в которой работает CentOS, возможно, в 32-разрядном режиме Обратите внимание, как одна и та же программа выдает гораздо большие значения для всех сегментов, в основном из-за разного кода запуска библиотеки C. main Сама функция должна использовать от нескольких байтов до максимум нескольких десятков в зависимости от параметров компиляции.

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

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

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

Современные операционные системы обрабатывают гораздо больше сегментов и тонкостей, связанных с исполняемыми программами. Вышеуказанный упрощенный подход моделирует структуру памяти исполняемых программ в ранних системах Unix в 1970-х и 1980-х годах. Имена предшествуют Unix почти на 2 десятилетия. Более подробную информацию можно отобразить с помощью утилит objdump и nm.

Вы можете прочитать подробное объяснение стандартных имен сегментов Unix здесь:

текст: https://en.wikipedia.org/wiki/Code_segment

данные: https://en.wikipedia.org/wiki/Data_segment

bss: https://en.wikipedia.org/wiki/.bss

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