Проблемы размещения памяти в 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