Как память, куча и стек управляются, реализуются, распределяются? - PullRequest
11 голосов
/ 31 июля 2009

В C / C ++ мы можем хранить переменные, функции, функции-члены, экземпляры класса либо в стеке, либо в куче.

Как каждый реализован? Как это управляется (высокий уровень)? Gcc предварительно распределяет кусок памяти, который будет использоваться для стека и кучи, и затем выдает по запросу? Исходная память идет из ОЗУ?

Может ли функция размещаться в куче вместо стека?

Разъяснение

Я действительно спрашиваю о реализации и управлении памятью кучи и стека. Прочитав указанный вопрос, Я не нашел ничего, что касалось бы этого ... спасибо за ссылку

Ответы [ 2 ]

5 голосов
/ 03 августа 2009

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

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

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

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

В противоположность этому, память в куче выделяется с помощью new / delete, для которого компилятор вставляет код для запроса или освобождения памяти с использованием системной библиотеки.

Обратите внимание, что это упрощенное описание, чтобы дать вам представление о том, как работает распределение памяти.

4 голосов
/ 02 августа 2009

По сути, куча реализуется не компилятором, а библиотекой времени выполнения C. Очевидно, этот код очень зависит от платформы. В Unix или Unix-подобных системах реализация обычно основана на системном вызове sbrk / brk, и для сокращения количества системных вызовов выделяется больший объем памяти. Затем эта память управляется диспетчером памяти кучи. Если требуется больше памяти, выдается новый вызов sbrk. Текущий конечный адрес кучи можно получить с помощью sbrk (0), если вы заинтересованы в отладке подпрограмм управления кучей. Большинство менеджеров памяти не возвращают память в ОС в течение времени жизни процесса (библиотека времени выполнения gnu c делает, если соблюдены определенные ограничения).

Более подробное описание доступно в http://gee.cs.oswego.edu/dl/html/malloc.html.

...