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