Cтраница 2
Строка типа string существует, пока счетчик ссылок на нее не равен нулю, а значение типа PChar никак не влияет на счетчик ссылок. [16]
![]() |
Циклический список со специальным головным элементом. [17] |
При обнаружении такого указателя следует уменьшить счетчик ссылок списка, на который он указывает, и проверить соответствующий счетчик на равенство нулю. [18]
Представленный в предыдущем разделе подход, заключающийся в размещении счетчика ссылок внутри указателей, может быть распространен на тот случай, когда значение счетчиков превышает единицу. [19]
Основная мысль заключается в том, что теперь в ячейках будет храниться обычный счетчик ссылок, а в указателях - веса, сумма которых для каждой адресуемой с их помощью ячейки равна значению счетчика этой ячейки. Теперь при копировании указателя, как и в однобитовой схеме в разд. [20]
![]() |
Взвешенные счетчики ссылок. [21] |
При удалении указателя его вес, однако, должен быть вычтен из счетчика ссылок в ячейке согласно основному правилу, по которому сумма весов равна значению этого счетчика. [22]
![]() |
Циклический список со счетчиками ссылок. [23] |
Циклические структуры, однако, не самая главная трудность, связанная с применением счетчиков ссылок. Во многих случаях циклические структуры не допускаются или встречаются столь редко, что возможное появление мусора не представляет серьезной опасности. Более важным фактором является стоимость работы со счетчиками ссылок. Во время выполнения непрерывно должны происходить проверки счетчиков ссылок, их увеличение и уменьшение. Часто это вызывает значительное снижение эффективности выполняемой программы. Рассмотрим, например, простое присваивание Р: Q, где Р и Q - переменные типа указатель. [24]
Существуют три основных класса сборщиков мусора: сканирующий, копирующий и сборщик на основе счетчиков ссылок. [25]
В таком случае обработка счетчиков ссылок будет необходима только для этих специальных элементов с переменными счетчиками ссылок, рассмотрим, например, систему oOj работки списков, в которой каждый связанный список считается отдельной структурой данных. Если мы снабдим каждый список специальным головным элементом и потребуем, чтобы указатели из других списков указывали только на эту голову, но не на внутренние элементы списка, то счетчик ссылок будет необходим только в головном элементе. Более того, в счетчике ссылок головы нужно подсчитывать только указатели извне данной структуры. Все это изображено на рис. 7.9. Отдельные элементы можно удалять из списка и сразу же возвращать в список свободного пространства, не учитывая счетчики ссылок. Когда счетчик ссылок головы станет нулевым ( например, в результате уничтожения указателя, записанного в другом списке), то весь наш список - голова и все элементы - может быть возвращен в список свободного пространства. [26]
Стандартная реализация этого метода, как и реализация, предоставляемая TlnterfacedObject, приводит к увеличению счетчика ссылок на объект. Реализация метода Release классом TlnterfacedObject уменьшает счетчик ссылок, проверяя, не имеет ли он значение ноль, и в случае необходимости уничтожает объект. Вот поэтому в предыдущем примере нет программного кода, освобождающего ресурсы, используемые созданным объектом. [27]
Основным же недостатком этой схемы является то, что, во-первых, она требует дополнительного места для размещения счетчиков ссылок в ячейках, а во-вторых, как и в сканирующем алгоритме, происходит фрагментация кучи, поскольку активные ячейки не перемещаются. [28]
Строка типа string существует, пока счетчик ссылок на нее не равен нулю, а значение типа PChar никак не влияет на счетчик ссылок. [29]
Хотя теперь сборка мусора будет происходить в ленивом режиме, не исключено, что в стеке может скапливаться большое число адресов ячеек, чьи счетчики ссылок больше единицы. Другими словами, большинство ячеек не являются разделяемыми. [30]