Содержание статьи
Споры на эту тему вообще нередко звучат как «чистый С против остальных языков». В действительности автоматическое управление памятью в С вполне возможно и применяется на практике, да и «остальные языки» и разные их реализации сильно отличаются друг от друга.
Ошибки управления памятью
Для начала вспомним, от чего нас спасает автоматическое управление памятью.
Первая и самая известная, но при этом не самая опасная — утечка памяти (memory leak). Утечка происходит, если запросить у ядра ОС память и забыть ее вернуть. В терминах языка С — вызвать malloc(
и забыть free(
. Программа с этой проблемой будет занимать все больше и больше памяти, пока ее не остановит пользователь или сама ОС. Поведение программы при этом остается корректным, и проблем с безопасностью утечки не вызывают.
Вторая проблема — висячие указатели (dangling pointers). Суть проблемы в том, что в программе остается указатель на участок памяти, который уже был освобожден. Для повторного обращения к такой памяти есть отдельный термин — use after free. Такие ошибки гораздо опаснее, и последствия могут быть самыми разными: от сложных в отладке глюков до возможности выполнить произвольный код — база CVE не даст соврать.
Более редкий вариант проблемы с висячим указателем — повторное освобождение (double free), которое уничтожает полезные данные.
Таким образом, от решения для автоматического управления требуются два свойства: никогда не удалять из памяти объекты, на которые есть живые указатели, и по возможности не оставлять в памяти объекты, на которые живых указателей нет.
Что делает сборщик мусора?
Упрощенно можно сказать, что при запуске у программы есть непрерывный диапазон адресов, куда она может поместить свои данные. Программа с автоматическим управлением памятью сразу при запуске запрашивает у ОС область памяти под «кучу» (heap). Начальный размер кучи часто (но не всегда) можно настроить во время компиляции или выполнения. При выполнении программы размер кучи может расти.
После этого сборщик мусора периодически следит за тем, какие участки памяти еще содержат нужные данные, а какие можно освободить и заполнить новыми данными. Как именно он это делает — зависит от реализации, но об этом дальше. Для начала развеем более простые мифы.
Сборщик мусора — часть языка?
Часто можно услышать утверждения вроде «Ruby — язык со сборкой мусора» или «С — язык с ручным управлением памятью». Первое утверждение верно в том смысле, что ни одна реализация Ruby не предоставляет возможность управлять памятью вручную.
Со вторым утверждением сложнее. Сборка мусора не входит в спецификацию языка С. Тем не менее спецификация ее и не запрещает. Спецификация языка ада также не навязывает авторам компиляторов какую‑то конкретную модель управления памятью, но некоторые компиляторы при этом предоставляют опциальный сборщик мусора.
Такие компиляторы С мне неизвестны, но на практике автоматически управлять памятью в программах на С вполне возможно с помощью сторонних библиотек.
Для примера мы возьмем Boehm GC. Это весьма зрелый и функциональный продукт, который использовали или поныне используют множество проектов: как приложений (например, векторный графический редактор Inkscape), так и реализаций языков программирования.
Используем Boehm GC
Многие дистрибутивы Linux предоставляют пакет с Boehm GC в репозиториях, чаще всего под именем libgc
. В Fedora его можно поставить командой sudo
, в Debian — sudo
.
Для демонстрации мы напишем программу, которая непрерывно запрашивает память под массив из тысячи целых чисел, но никогда ее не освобождает. Если бы мы использовали для выделения памяти классический malloc(
, это была бы хрестоматийная утечка памяти. Но мы обратимся не напрямую к ОС, а к менеджеру памяти Boehm GC с помощью функции GC_MALLOC(
и посмотрим, что будет.
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»