Опубликован: 23.07.2006 | Доступ: свободный | Студентов: 2215 / 889 | Оценка: 4.28 / 4.17 | Длительность: 21:37:00
Специальности: Системный архитектор
Лекция 10:

Управление памятью и сборка мусора

Проблемы управления памятью

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

Другая проблема возникает в тех случаях, когда язык программирования предоставляет программисту явный механизм управления памятью (такой, как malloc/free в языке С или new/delete в С++). В этих случаях компилятор не может гарантировать правильность работы обрабатываемых им программ и эта ответственность возлагается на программиста. К сожалению, люди значительно менее надежны, имеют тенденцию ошибаться и даже повторять свои ошибки, а во многих случаях и попросту игнорируют предоставленные им механизмы. Поэтому при таком подходе обычно возникает множество ошибок, что, в свою очередь, ведет к необходимости кропотливой отладки программ и существенно затрудняет работу программиста.

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

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

Проблемы управления памятью (окончание)

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

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

Затем освобожденную память необходимо вернуть системе как свободную - утилизировать. Отметим, что операции уничтожения памяти и утилизации могут быть сильно разнесены по времени. Более того, в большинстве языков у программиста нет возможности форсировать утилизацию данного конкретного объекта (хотя в C# такая операция предусмотрена для крупных объектов).

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