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