Виды памяти | OTUS
⚡ Подписка на курсы OTUS!
Интенсивная прокачка навыков для IT-специалистов!
Подробнее

Курсы

Программирование
Python Developer. Professional
-3%
Разработчик на Spring Framework
-5%
iOS Developer. Professional
-8%
Golang Developer. Professional
-6%
Agile Project Manager
-5%
C# ASP.NET Core разработчик
-6%
Android Developer. Basic
-10%
React.js Developer
-4%
MS SQL Server Developer
-8%
Scala-разработчик
-8%
Java Developer. Basic
-8%
Разработчик IoT
-13%
PostgreSQL Backend-разработчик на PHP Алгоритмы и структуры данных Разработчик программных роботов (RPA) на базе UiPath и PIX Unity Game Developer. Basic Разработчик голосовых ассистентов и чат-ботов Vue.js разработчик VOIP инженер NoSQL Супер-практикум по использованию и настройке GIT Symfony Framework iOS Developer. Basic Супер-интенсив «СУБД в высоконагруженных системах» Супер-интенсив "Tarantool"
Инфраструктура
DevOps практики и инструменты
-12%
Network engineer. Basic
-10%
Network engineer
-4%
Экcпресс-курс «ELK»
-10%
Инфраструктурная платформа на основе Kubernetes
-6%
Экспресс-курс по управлению миграциями (DBVC)
-10%
Мониторинг и логирование: Zabbix, Prometheus, ELK Дизайн сетей ЦОД
-13%
PostgreSQL Administrator Linux. Professional Разработчик программных роботов (RPA) на базе UiPath и PIX Reverse-Engineering. Professional Внедрение и работа в DevSecOps Administrator Linux. Advanced Infrastructure as a code in Ansible Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Экспресс-курс «IaC Ansible»
Специализации Курсы в разработке Подготовительные курсы
+7 499 938-92-02

Виды памяти

VKС++Deep_21.06_Site.png

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

Поясним на примерах на языке С++

Исполняемый код программы хранится в сегменте кода. Данный сегмент защищён от записи, и, как правило, обычным программистам не требуется выполнять над ним каких-либо действий. Простейший и, возможно, единственный пример работы с сегментом данных — получение указателя на функцию. Значение указателя на функцию — это адрес точки входа в эту функцию в сегменте данных.

Глобальные данные (т. е. переменные, объявленные вне какой-либо функции и вне функции main) будут размещены в сегменте данных. При этом глобальные переменные с модификатором const размещаются в защищённом от записи сегменте данных (или сегменте констант), и любая попытка их изменения посредством применения const_cast приведёт к аварийному завершению программы. При разработке необходимо учитывать, что все глобальные данные инициализируются до входа в функцию main, а уничтожаются после выхода из main.

Данные, объявленные внутри какой-либо функции (т. е. локальные данные), будут хранится в стеке. Это относится и к функции main. Поскольку main является точкой входа в программу, локальные данные, объявленные в main, будут хранится на дне стека. По мере вызова других функций из функции main стек будет использоваться для хранения локальных данных вызываемых функций. При возврате из функции все её локальные данные уничтожаются и стек очищается.

После возврата стек будет содержать локальные данные вызывающей функции. Исключение составляют строковые литералы — т. е. переменные или константы вида

char* str = “Hello World!”

или

const char* str = “There is a rabbit”

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

При разработке многопоточных программ необходимо понимать, что каждый поток будет иметь свой стек, но сегменты данных будут общими для всех потоков вашего приложения. Кстати, не многие программисты знают, что память динамически можно также выделять и на стеке. В языках С и С++ для этого служит функция alloca. Важно понимать, что динамически выделенная на стеке память освобождается автоматически при выходе из функции, которая её выделила. Таким образом, этот блок памяти существует только в контексте функции, которая его выделила.

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

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

Нередко в сложных многопоточных приложениях эта задача становится довольно трудной и ведёт к аварийным завершениям программы и/или утечкам памяти. Здесь приходит на помощь замечательное нововведение стандарта С++11 — умные указатели.

Есть вопрос? Напишите в комментариях!

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться