10. C/C++ Организация памяти и выполнение программ, стек и куча

C/C++ Организация памяти и выполнение программ, стек и куча

Для начала вспомним как работает вычислитель (рассмотрим весьма утрированно, не погружаясь в работу АЛУ, РОН и тд)

Внутри вычислителя есть память, в которой находится код программы (обычно это RAM / ОЗУ) внутри памяти каждый байт имеет смещение относительно начала памяти, именно это смещение и называют адресом в памяти.
Внутри памяти хранятся текущие операнды и действия над ними (разумеется в бинарном виде и виде инструкций) и они последовательно (многопоточность и параллельность пока оставим за кадром) выполняются с каждым тактом.

1 шаг – адрес 0x013FFF01 инструкция/операнд …
2 шаг – адрес 0x013FFF02 например переход + 4 адреса
3 шаг – адрес 0x013FFF07 …

Т.е. что мы имеем – внутри вычислителя есть память, в которой находится программа, но ведь программ может быть много, и нет гарантий что программа занимает ВСЮ оперативную память. Каждая следующая вызванная функция/программа обычно расположена в памяти с большим адресом, и является первой на освобождение (очищение).
Т.е. если смотреть на таблицу – то вызываются функции сверху вниз, а освобождаются снизу вверх.
Выделяем память: Запустили операционную систему->открыли браузер
Очищаем память: закрыли браузер -> завершили работу ОС

Память под программу рассчитывается на этапе КОМПИЛИРОВАНИЯ и ЛИНКОВКИ и выделяется в процессе выполнения программы.

Следовательно

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

Данная память, рассчитанная на этапе компиляции/линковки и выделенная в ходе запуска программы называется стеком (stack).

Следует еще раз акцентировать внимание, что программы запускаются по принципу LIFO (Last In, First Out),  то есть последний добавленный в стек кусок памяти будет первым в очереди на вывод из стека.

Звучит хорошо и красиво, но при работе с данными мы не всегда можем знать сколько еще памяти нам понадобится, что же делать? Ведь память на стеке уже выделена?
Для этого можно использовать остальную память – она называется куча (heap). В ходе работы программы мы можем динамически (по своему хотению, в любой момент времени, при наличии свободного места) выделять дополнительную память и работать через ее адреса.
Эта дополнительная память, выделенная в куче и с которой работают из стека называется динамической памятью.Схематично стек и куча обозначены на рисунке, из области памяти DataN указатель *ptr ведет в область кучи, где динамически выделена память.

Примечание: На самом деле не всегда стек и куча расположены в одной зоне памяти, физически для более быстрого выполнения стек может быть перенесен в область кэш (cash) процессора (эта память обычно существенно быстрее оперативной), но за счет адресации и работы ide данные

 

Важно отметить, что разработчик сам выделяет память в куче, чем может ограничить работу других программ, в C++ компилятор не отслеживает выделение памяти пользователем и указатели/ссылки на нее, поэтому если указатель будет утерян (удален), то область в куче так и останется выделенной до перезапуска программы/ перезапуска вычислителя.
Данный механизм потери памяти из-за потери указателя называется утечками leaks.
Если утечек будет много – память закончится и код не сможет выполняться.

Leave a Reply

Your email address will not be published. Required fields are marked *