Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Деревья и кольцевые ссылки
 
 автор: St.Devil   (09.10.2009 в 00:54)   письмо автору
 
 

Имеется класс дерева, что-то типа

class Tree {

    protected $RootNode;

}


И класс узла, что-то типа

class Node {

    protected $Tree;
    protected $ParentNode;
    protected $ChildNodes = array();

}


Предпологается, что текущий узел хранит ссылки на дерево, родительский узел и дочерние узлы, а родительский узел хранит ссылку на текущий узел (в $ChildNodes), дочерние узлы хранят ссылку на текущий узел (в $ParentNode) и дерево хранит ссылку на корневой узел.
Получаются кольцевые ссылки (когда объекты хранят ссылки на друг друга), а сборщик мусора не умеет обрабатывать такие ситуации и объекты остаются в памяти, даже если видимых ссылок в программе на них не осталось.
Подскажите, пожалуйста, решение проблемы удаления объектов дерева и узлов?

  Ответить  
 
 автор: Саня   (09.10.2009 в 08:49)   письмо автору
 
   для: St.Devil   (09.10.2009 в 00:54)
 

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

  Ответить  
 
 автор: St.Devil   (09.10.2009 в 08:59)   письмо автору
 
   для: Саня   (09.10.2009 в 08:49)
 

Например:

public function foo(){
    $tree = new Tree();
    $child_node = $tree->createNode();
    $tree->RootNode->addNode($child_node);
    return;
}


Ресурсы не освободятся, т.к. узлы будут хранить ссылки друг на друга и на дерево, которое в свою очередь будет хранить ссылку на корневой узел.
Вы предлагаете освобождать ресурсы в ручную (например $tree->clear()) каждый раз, когда необходимо уничтожить дерево?
А что если кто-нибудь из разработчиков (в команде их много) забудет это сделать? Память будет занята до конца работы скрипта, а дерево может быть очень большое. И как потом искать в огромном проекте, где забыли очистить дерево?
Может существует корректный способ освобождения памяти сброщиком мусора? Может нужно как то классы дерева и узла по-другому организовать?

  Ответить  
 
 автор: Саня   (09.10.2009 в 09:07)   письмо автору
 
   для: St.Devil   (09.10.2009 в 08:59)
 

Деструкторы для кого придуманы?

  Ответить  
 
 автор: St.Devil   (09.10.2009 в 09:15)   письмо автору
 
   для: Саня   (09.10.2009 в 09:07)
 

Автоматически деструктор вызывается с помощью сборщика мусора, который его не вызовет, пока на объект есть хотя бы одна ссылка.
Попробуйте выполнить у себя код:

class Tree {
    
    protected $RootNode;
    
    public function __construct(){
        $this->RootNode = new Node($this);
    }
    
    public function __destruct(){
        echo '<div>Tree destruct</div>';
    }
}

class Node {
    
    protected $Tree;
    
    public function __construct(Tree $tree){
        $this->Tree = $tree;
    }
    
    public function __destruct(){
        echo '<div>Node destruct</div>';
    }
}

$tree = new Tree();
unset($tree);

echo '<div>Script finish</div>';


Результатом будет:

Script finish
Tree destruct
Node destruct

Т.е. деструкторы Tree и Node вызовутся уже после завершения работы скрипта, хотя единственная видимая ссылка на дерево была удалена до вывода сообщения о завершении работы скрипта

  Ответить  
 
 автор: GeorgeIV   (09.10.2009 в 10:01)   письмо автору
 
   для: St.Devil   (09.10.2009 в 09:15)
 

У вас скрипт висит вечно? Скрипт отработает и сборщик подчистит весь мусор.

  Ответить  
 
 автор: St.Devil   (09.10.2009 в 10:16)   письмо автору
 
   для: GeorgeIV   (09.10.2009 в 10:01)
 

А если деревьев несколько? Зачем хранить в памяти деревья (особенно если они огромные), с которыми уже не нужно будет работать?

  Ответить  
 
 автор: Саня   (09.10.2009 в 17:02)   письмо автору
 
   для: St.Devil   (09.10.2009 в 09:15)
 

Обязательно связывать Tree с нодами? Нельзя ноду сделать булевое поле "isRoot", указывающее на то, что он корневой? И вместо protected $Tree; сделать protected $RootElement;

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования