Программирование >>  Формирование пользовательского контейнера 

1 ... 3 4 5 [ 6 ] 7 8 9 ... 156


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

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

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

Реализация сборщика мусора

Для того чтобы создать сборщик мусора с использованием алгоритма полсчета ссылок, должен быть найден способ хранения сведений об указателях, ссылающихся на каждый фрагмент динамически вьщеленной памяти. Однако в языке С++ нет встроенного механизма, который бы позволил одному объекту узнать о том, что другой объект на него указывает. К счастью, есть решение: вы можете создать новый тип указателя для сбора мусора. Именно такой подход будет реализован в сборщике мусора, приведенном в данной главе. Для поддержки процесса сбора мусора новый тип указателя должен уметь делать следующее:

□ поддерживать список счетчиков ссылок для активных динамически размещенных объектов;

О отслеживать операции с указателями: увеличивать на единицу счетчик ссылок объекта каждый раз, когда указатель указывает на этот объект, и уменьшать значение счетчика на ту же величину, когда указатель перенаправляется на другой объект;

П освобождать те объекты, счетчики ссылок которых равны нулю.



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

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

Использовать ли многопоточность?

Следует принять еще одно решение при проектировании сборщика мусора для С++: должен он быть однопоточным или многопоточным. Другими словами, должен ли сборщик мусора проектироваться как фоновый процесс, выполняющийся в своем потоке и собирающий мусор, когда позволит время процессора? Или сборщик мусора будет функционировать в том же потоке, что и процесс, его использующий, и собирать мусор тогда, когда возникает определенная ситуация в программе? Оба подхода обладают как достоинствами, так и недостатками.

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

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

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

Когда собирать мусор?

Прежде чем приступить к разработке сборщика мусора, надо ответить еще на один, последний вопрос: когда собирать мусор? Ответ на него менее важен для многопоточного сборщика мусора, который может выполняться



То есть теряет связь с любыми программными элементами. - Пер.

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

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

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

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

Можно ли применить auto pti

Как известно многим читателям, язык С++ определяет библиотечный класс под названием auto ptr. Поскольку auto ptr автоматически освобождает память, на которую он указывает, когда указатель выходит за пределы области видимости, вы можете решить, что его хорошо было бы использовать при разработке сборщика мусора, возможно, для формирования основы. К сожалению, это не тот случай. Класс auto ptr создан для реализации концепции, именуемой в стандарте ISO языка С++ строгим владением (strict ownership).



1 ... 3 4 5 [ 6 ] 7 8 9 ... 156

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика