💻 ПРОГРАММИРОВАНИЕ

Что такое сборщик мусора и почему память не убирается сама собой

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

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

Память — это одолженный стол

Представьте память как большой рабочий стол. Когда программе нужно где-то разместить данные — список покупок, картинку, текст, — она занимает кусочек стола. Проблема в том, что стол не бесконечен. Если занимать места всё больше и никогда не освобождать, рано или поздно оно кончится, и программа упадёт с нехваткой памяти.

Значит, отработанные данные нужно убирать. Вопрос — кто это делает: человек или машина.

Ручная уборка и её опасности

В языках вроде C убирать за собой обязан программист: явно сказать «эта память больше не нужна, освободи». Звучит просто, но на практике это источник самых противных багов. Забыл освободить — память утекает, программа со временем разбухает. Освободил, но где-то ещё осталась ссылка, и по ней обратились — обращение к уже освобождённой памяти, почти гарантированный сбой. Освободил дважды — тоже беда.

Автоматическая уборка

Чтобы снять эту ношу с человека, придумали сборщик мусора (garbage collector, GC). Это часть среды выполнения языка, которая сама следит за памятью. Так работают Java, Python, JavaScript, C#, Go и многие другие — там о ручном освобождении думать почти не нужно.

Как он понимает, что мусор, а что нет

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

Классический способ это вычислить — «пометить и убрать» (mark-and-sweep): сборщик стартует от корней (активных переменных), обходит все ссылки и помечает всё достижимое. Что не помечено — недостижимо, значит, мусор, и эту память можно вернуть. Есть и другой приём — подсчёт ссылок: каждое значение помнит, сколько ссылок на него указывает; счётчик упал до нуля — память свободна.

Подход к памятиКто убираетРиск утечекЦена
Ручной (C)ПрограммистВысокийСложность, баги
Сборщик мусораСреда выполненияНизкийРесурсы, паузы
Владение (Rust)Компилятор заранееНизкийСложнее писать

Цена удобства

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

Так нужен ли он

Сборщик мусора — это сделка: вы отдаёте немного производительности и контроля, а взамен получаете огромную экономию сил и защиту от целого класса ошибок. Для большинства задач это отличный обмен — недаром им оснащены самые популярные языки. А там, где каждая миллисекунда на счету, выбирают ручное управление или подход вроде Rust, где порядок наводит не уборщик во время работы, а компилятор заранее.

#garbage collector#основы#память#сборщик мусора