Определение

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

Одно из наиболее необычных понятий в мире компьютерного программного обеспечения, особенно в Windows, — это утечка памяти. Это характерный пример нестабильности в поведении системы, проявляемой с течением времени, и она может вылиться в серьезную проблему. Если программа работает длительное время, даже небольшая утечка в конечном итоге неизбежно приведет к сбою программы или системы, поскольку постепенно блокируется все больше и больше ресурсов до тех пор пока все они не будут исчерпаны.

Утечка памяти

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

По мере работы программы ей иногда требуется все больше памяти, и она инициирует дополнительные запросы. Теперь мы переходим к одному из правил хорошего программирования. Любая запрашиваемая и резервируемая память должна обязательно освобождаться прикладной программой, когда в ней (памяти) больше нет необходимости, и в любом случае — при завершении приложения. О программе, которая следует такому правилу, говорят, что она «хорошо себя ведет».

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

Но программные объекты могут порождать другие «побочные эффекты», которые не прекращаются после завершения работы программы. Программист никогда не должен рассчитывать на то, что объекты выполняют только корректные операции, которые заканчиваются при завершении программы.

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

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

Сборка мусора

Освобождение операционной системой для повторного использования пространства, которое было блокировано вследствие утечек памяти, называется сборкой мусора. В прошлом программы должны были запрашивать точный объем необходимой им памяти и затем, когда она больше не требовалась, возвращать ее системе. Термин «сборка мусора» впервые возник с появлением языка программирования Лисп, разработанного в 60-х. Некоторые операционные системы предлагают средства обнаружения утечки памяти, в силу чего проблема может быть выявлена еще до того, как в приложении или операционной системе возникнет сбой.

Некоторые инструментальные средства разработки программ, например комплект инструментов для программирования на языке Java, также предоставляют разработчику автоматические служебные функции. Реальное преимущество в этом случае состоит в том, что процесс выполняется вне зависимости от того, рассчитывает на него программист или нет.


Кап, кап, кап

1. Эта сетка представляет память компьютера. Голубыми квадратиками изображена память, используемая операционной системой, а коричневыми — память, занятая под системные утилиты и программы. Теперь мы запускаем три приложения — A, B и C (оранжевый, зеленый и желтый соответственно). Каждое из приложений запрашивает и получает фрагмент памяти от операционной системы. До этого момента все просто и ясно.

2. Прошло время. Программа A завершилась, не сообщив ОС о том, что зарезервированная ею память ей больше не нужна. Эта область на рисунке закрашена красным цветом, чтобы показать, что данная память недоступна. Это классический пример утечки памяти. Программа C, спроектированная лучше, чем Программа A, завершается. Хотя она возвращает большую часть своей памяти, тем не менее оставляет неосвобожденными несколько битов. Эта утечка разрушает целый блок, затрудняя эффективное использование пространства.

3. Завершается приложение B и возвращает обратно всю свою память. Но запускается приложение D, которому требуется цепочка из 20 подряд идущих блоков. Но цепочек такой длины нет. Самый большой фрагмент, включающий в себя всю память, которую использовала Программа B и первая часть C (окрашенный в бирюзовый цвет) состоит из 14 блоков. Операционная система не в состоянии предоставить Программе D всю необходимую память.

4. ОС должна объединить вместе все неиспользуемые области памяти (отмеченные красным цветом). Она может найти область, с которой работала теперь закрытая Программа A и понять, что, хотя память все еще «зарезервирована», она больше не используется. ОС выбирает все, что находится в этой области памяти, и копирует ее содержимое в «файл подкачки» на жесткий диск, где эта информация остается до тех пор, пока она не потребуется. В результате ОС освобождает память и маркирует ее как доступную, а затем проверяет, хватает ли ее для нужд Программы D.

5. Однако в тех случаях, когда утечка затронула достаточно большое количество памяти, доступное пространство становится слишком фрагментированным (так же, как жесткий диск) и распределяется так, что его становится невозможно использовать. В этом случае операционная система не в состоянии реально исправить ситуацию эффективным образом. Единственное возможное решение — это перезагрузка.