Использование памяти программой не зависит от языка, на котором написана эта программа. Вы можете написать код, который использует тонну памяти в C #, вы можете сделать то же самое в C.
Тем не менее, я постараюсь ответить на некоторые из ваших вопросов:
как хранятся и обрабатываются глобальные переменные
Им даны адреса памяти. Когда вы используете глобальный, компилятор просто использует этот известный адрес. (Что, ты ожидал сложного ответа?)
что глобальные переменные находятся в конце программного кода
На некоторых архитектурах это может иметь место, но это не обязательно. В Windows (с использованием формата файла Portable Executable) они никак не связаны и могут быть сопоставлены с совершенно разными произвольными местоположениями. На самом деле, скорее всего, это не относится к более поздним архитектурам, которые препятствуют размещению кода там, где находятся данные (в целях безопасности - вы не хотите, чтобы переполнение буфера позволяло перезаписывать код вашей программы)
если я не ошибаюсь, в современных операционных системах x86 каждая программа получает свое собственное адресное пространство, начиная с 0
Вы не ошибаетесь в теории, но вы ошибаетесь на самом деле. Даже если бы линкеры действительно могли это сделать, мало кто бы это сделал, просто потому что 0 используется как константа null
. Однако обычно проблема заключается в том, что существуют динамические библиотеки или другие элементы, которые потребляют части адресного пространства вашего процесса, задолго до того, как ваш код будет фактически загружен. (Например, ссылка на файл, в котором находится ваш код, или блок памяти, содержащий командную строку, переданную вашей программе)
Я прочитал, что выделение памяти с помощью malloc увеличивает кучу
Ну, вы предполагаете, что есть только одна куча. По крайней мере, в Windows каждая DLL обычно имеет свою собственную кучу, и вы можете создавать кучи на лету / по желанию. Классические объяснения кучи в курсах информатики обычно предполагают систему, в которой нет базовой операционной системы или виртуальной памяти в игре.
Вы путаете память с адресным пространством здесь для современных процессоров. Адресные местоположения вещей часто имеют мало общего с тем, где они физически хранятся. Статья в Википедии о Виртуальная память может сделать ваши вещи более понятными. Удачи!
EDIT:
exe-файл PE на самом деле содержит информацию о глобальных переменных, которую можно отличить от других данных
Не совсем. Формат файла PE имеет раздел, в котором хранятся статические данные, и эта область файла отображается в памяти. Код знает, где находится этот большой кусок, где находятся конкретные глобалы, которые вы ищете.
То, что Os фактически отображает их, скажем, «лучшее» доступное пространство
Современные процессоры используют модель с плоской памятью. Так же легко получить доступ к любому адресу, как и к любому другому.
Я всегда думал, что скомпилированный код больше не изменяется ОС во время выполнения
Это не так (по большей части причина, по которой это может измениться, - целая банка червей самих по себе). Чтобы получить доступ к глобальному, сам код должен знать базовый адрес 1055 *, по которому он загружен. Он может вычислить, где блок данных файла PE загружается из этого, по большей части. Тем не менее, компиляторы могут размещать глобальные переменные практически везде; тот факт, что в спецификации PE есть место для инициализированных данных, не означает, что компилятор должен его использовать (например, MingGW не использует эту область).
Во-первых, содержит ли .exe информацию о необходимом размере стека?
Да, есть настройки, управляющие как зарезервированным размером стека, так и фиксированным размером стека. Поскольку переполнение стека можно безопасно обрабатывать в Windows, обычно размер стека составляет всего 1 МБ; на * nix машинах обычно 8 МБ или больше.
И ограничен ли размер стека?
Не настолько, насколько я знаю.Это сказал;Есть, конечно, практические ограничения.Прежде всего, адресное пространство, зарезервированное для стека, не будет использоваться ни для чего, кроме стека.Существуют также большие части адресного пространства, которые зарезервированы ядром для различных целей;не говоря уже о реальном коде и данных, с которыми работает ваша программа.Если вы используете более 1 МБ стека, вам следует подумать об использовании выделенного кучи стека для ваших данных и переключиться на итеративное решение или серьезно переосмыслить работу вашей программы.1 МБ стека - это намного больше, чем обычно используется.
И, во-вторых, есть ли какая-либо статья, о которой вы сейчас пишете, которая содержит эту информацию и / или информацию о том, что такое контент в формате PE, как это происходит?закодирован, чтобы его можно было увидеть при разборке .exe файла
Вы можете прочитать спецификацию PE: http://www.microsoft.com/whdc/system/platform/firmware/pecoff.mspx
В современных системах вы можете по существу забыть о точном знании, где кодсегменты и данные расположены как физически, так и виртуально.Процессор не заботится и не применяет ничего подобного, поэтому нет причин, по которым любая операционная система или программа вынуждена использовать какую-либо организацию памяти.В частности, концепция кучи в Windows сильно отличается от того, что обычно преподается на курсах информатики.В Windows (и других современных ОС) куча - это не что иное, как куча памяти, выделенная ОС.Местоположение этой памяти, однако, полностью изменчиво.Запросите ОС для одного блока, вы можете получить его по адресу 0x00005556, а следующий блок - по 0xFFFF890.Нет никаких причин для различия, потому что процессор под ним просто не заботится.