За последние 24 часа нас посетили 18820 программистов и 1613 роботов. Сейчас ищут 944 программиста ...

unset не уничтожает класс полностью, если он передан куда ли

Тема в разделе "PHP для новичков", создана пользователем mrsol, 14 фев 2008.

  1. mrsol

    mrsol Активный пользователь

    С нами с:
    26 мар 2007
    Сообщения:
    17
    Симпатии:
    0
    Есть два класса, в одном создаётся другой, и другому передаётся по ссылке первый. Он у себя это запоминает. Потом пытюсь уничтожить первый класс командой unset . Класс пропадает, становится NULL и должен якобы пропасть класс который был создан внутри. Но вот функция __destruct отрабатывается, только тогда, когда скрипт заканчивает работу.
    То есть остаётся где-то копия данного класса, к которой я не могу получить доступ.
    Вопрос. Как нормально уничтожать такие объекты, чтобы отрабатывался __destruct. И все копии сколько их бы не было уничтожались.

    Вот на этом коде проводил тестирование.
    PHP:
    1. <?php
    2.  
    3.   class A{
    4.     public $parent_class;
    5.    
    6.     public function add_parent(&$class){
    7.         echo "Add parent class\n";
    8.         $this->parent_class = &$class;
    9.     }
    10.    
    11.     public function __construct(){
    12.         echo "Construct Class A\n";
    13.     }
    14.    
    15.     public function __destruct(){
    16.         echo "Desctruct class A\n";
    17.     }
    18.   }
    19.  
    20.   class B{
    21.     public $one_class;
    22.    
    23.     public function test(){
    24.         $this->one_class = new A;
    25.         $this->one_class->add_parent(&$this);
    26.     }
    27.    
    28.     public function __construct(){
    29.         echo "Construct Class B\n";
    30.     }
    31.    
    32.     public function __destruct(){
    33.         echo "Desctruct class B\n";
    34.     }
    35.   }
    36.  
    37.   echo "init class B\n";
    38.   $test_cl = new B();
    39.   echo "run test func\n";
    40.   $test_cl->test();
    41.   echo "try unset B\n";
    42.   unset($test_cl);
    43.   echo "now this class='".var_export($test_cl, true)."' \n";
    44.   echo "end script\n";
    45.  
    46. ?>
    Вывод дает следующий

    init class B
    Construct Class B
    run test func
    Construct Class A
    Add parent class
    try unset B
    now this class='NULL'
    end script
    Desctruct class B
    Desctruct class A


    Получается что объект $test_cl после unset сталл равен NULL. Но при этом в памяти где-то висит копия и как я понимаю занимает место.
     
  2. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    чтобы уничтожить объект нужно уничтожить все ссылки на него.
     
  3. mrsol

    mrsol Активный пользователь

    С нами с:
    26 мар 2007
    Сообщения:
    17
    Симпатии:
    0
    Есть ли какой-то способ уничтожения всех ссылок не зная их?
     
  4. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
  5. Ti

    Ti Активный пользователь

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    $object = null;
     
  6. Clone

    Clone Guest

    Что-то я не понимаю, как можно уничтожить класс и создать в классе другой класс... Может здесь всё заменить на "объекты класса"?
     
  7. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    Плакал.
    ООП наличия мозгов и этапа проектирования не отменяет.
     
  8. mrsol

    mrsol Активный пользователь

    С нами с:
    26 мар 2007
    Сообщения:
    17
    Симпатии:
    0
    Какие умные ответы, я аж плакал, особенно про мозги и проектирование.

    2Clone
    Ну сформулировала неправильно, бывает.
     
  9. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    - зачем вообще дается возможность самому писать деструкторы?
    - каким образом что-то еще может получить ссылку на объект внутри какого-то объекта?
     
  10. mrsol

    mrsol Активный пользователь

    С нами с:
    26 мар 2007
    Сообщения:
    17
    Симпатии:
    0
    PHP:
    1. <?php
    2.   class B{
    3.     private $just_a_var;
    4.    
    5.     public function test($var){
    6.         $var = strrev($var);
    7.         $global_c->just_a_var = $var;
    8.         //echo "Test var='".$var."' \n";
    9.         return $var;
    10.     }
    11.    
    12.     public function __construct($name){
    13.         $this->name = $name;
    14.         echo "Construct Class B name='".$this->name."'\n";
    15.     }
    16.    
    17.     public function __destruct(){
    18.         echo "Desctruct class B name='".$this->name."'\n";
    19.     }
    20.   }
    21.  
    22.   class D{
    23.     public $s_class;
    24.    
    25.     public function add_class(&$class){
    26.        
    27.         $this->s_class = &$class;
    28.     }
    29.    
    30.     public function test($var){
    31.        
    32.         $var = strtoupper($var);
    33.         return $this->s_class->test($var);
    34.     }
    35.    
    36.     public function __construct($name){
    37.         $this->name = $name;
    38.         echo "Construct Class D name='".$this->name."'\n";
    39.     }
    40.    
    41.     public function __destruct(){
    42.         echo "Desctruct class D name='".$this->name."'\n";
    43.     }
    44.   }
    45.  
    46.  
    47.   echo "construc class B\n";
    48.   $test_cl = new B('name_one');
    49.   echo "construc class D\n";
    50.   $test_D = new D('name_two');
    51.   echo "add in class D class B\n";
    52.   $test_D->add_class(&$test_cl);
    53.   echo "run func from D\n";
    54.   $ret = $test_D->test('abc');
    55.   echo "return ret='".$ret."' \n";
    56.   echo "Try unset class B\n";
    57.   unset($test_cl);
    58.   echo "Try unset class D\n";
    59.   unset($test_D);
    60.   echo "End Programm\n";
    61.  
    62. ?>
    63.  
    вывод
    php -q test11.php
    construc class B
    Construct Class B name='name_one'
    construc class D
    Construct Class D name='name_two'
    add in class D class B
    run func from D
    return ret='CBA'
    Try unset class B
    Try unset class D
    Desctruct class D name='name_two'
    Desctruct class B name='name_one'
    End Programm

    Покаместь D не будет убит С тоже не освободится.
    Это просто пример на коленке. И разговор идёт не об алгоритме и проектировке, а именно о ссылках к объектам. И каким образом полностью уничтожать объект.
     
  11. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    разумеется, с чего бы это ему убиваться. Это что ж тогда будет, объекты сами собой убиваться начнут.
     
  12. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    mrsol, пока в пхп не появится сборщика мусора учитывающего циклические сылки (а это тормоза) - связи объекта с другими нужно разрывать вручную.
     
  13. mrsol

    mrsol Активный пользователь

    С нами с:
    26 мар 2007
    Сообщения:
    17
    Симпатии:
    0
    Или ещё код. Наследования самого себя.
    PHP:
    1. <?php
    2.   class B{
    3.     private $child_class;
    4.     private $name;
    5.    
    6.     public function add_children(&$class, $counter){
    7.        
    8.         $t_counter = $counter;
    9.         echo "Add child class counter='".$counter."' \n";
    10.         if($counter<=0){
    11.             echo "Exit by counter\n";
    12.             return true;
    13.         }
    14.         $this->child_class = &$class;
    15.         $counter--;
    16.         $this->child_class->add_children($class, $counter);
    17.         echo "End add child class couner='".$t_counter."' \n";
    18.     }
    19.    
    20.     public function __construct($name, $count_child = 5){
    21.         $this->name = $name;
    22.         echo "Construct Class B name='".$this->name."'\n";
    23.         $this->add_children(&$this, $count_child);
    24.     }
    25.    
    26.     public function __destruct(){
    27.         echo "Desctruct class B name='".$this->name."'\n";
    28.     }
    29.   }
    30.  
    31.   echo "Init class\n";
    32.   $test_cl = new B('name_one', 3);
    33.   echo "Try unset\n";
    34.   unset($test_cl);
    35.   echo "Now variable is='".var_export($test_cl, true)."' \n";
    36.   echo "Try init second class for this variable\n";
    37.   $test_cl = new B('name_two', 3);
    38.   echo "Try unset second\n";
    39.   unset($test_cl);
    40.   echo "Now variable is='".var_export($test_cl, true)."' \n";
    41.   echo "End programm\n";
    42.  
    43. ?>
    Показывает
    php -q test12.php
    Init class
    Construct Class B name='name_one'
    Add child class counter='3'
    Add child class counter='2'
    Add child class counter='1'
    Add child class counter='0'
    Exit by counter
    End add child class couner='1'
    End add child class couner='2'
    End add child class couner='3'
    Try unset
    Now variable is='NULL'
    Try init second class for this variable
    Construct Class B name='name_two'
    Add child class counter='3'
    Add child class counter='2'
    Add child class counter='1'
    Add child class counter='0'
    Exit by counter
    End add child class couner='1'
    End add child class couner='2'
    End add child class couner='3'
    Try unset second
    Now variable is='NULL'
    End programm
    Desctruct class B name='name_one'
    Desctruct class B name='name_two'

    После первого унсета, доступа к этому классу у меня нет, так как ссылка на объект является NULL. Ещё раз создаю ссылку на объект на этой переменно и опять её убиваю. Итого у меня подвешано два объекта, к которым никак нельзя получить доступ. И будут висеть, до тех пор пока не закончит работу скрипт.

    Так до него дело и не доходит. Вернее доходит, но не тогда когда надо.
     
  14. Amian

    Amian Активный пользователь

    С нами с:
    15 мар 2007
    Сообщения:
    189
    Симпатии:
    0
    Сборщик мусора не будет вызываться до тех пор пока достаточно памяти, чтобы не было бесполезного overheading-a.
     
  15. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    mrsol, забудь про unset, он тебе не нужен. совершенно.
     
  16. mrsol

    mrsol Активный пользователь

    С нами с:
    26 мар 2007
    Сообщения:
    17
    Симпатии:
    0
    Знаете есть такое дерево. Фиг вам.
    mem='134,128,832'
    Init class xo='2753'
    Construct Class B name='name_one 2753'
    Add child class counter='2'
    Add child class counter='1'
    Add child class counter='0'
    Exit by counter
    End add child class couner='1'
    End add child class couner='2'
    Try unset

    Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 40961 bytes) in /home/slavik/sol/autonomic_sms_and_ussd/1/tested/test12.php on line 89


    2dark-demon
    А что использовать? Я не говорю что мне нужен именно unset
     
  17. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    ручной вызов деструктора, который порвёт исходящие связи.
    $obj->unlink();
     
  18. Amian

    Amian Активный пользователь

    С нами с:
    15 мар 2007
    Сообщения:
    189
    Симпатии:
    0
    mrsol
    Где-то я раньше читал что unset нельзя делать, попробуй просто обнулять указатели на объект.

    $blabla = new Blabla();
    $blabla = null;
     
  19. mrsol

    mrsol Активный пользователь

    С нами с:
    26 мар 2007
    Сообщения:
    17
    Симпатии:
    0
    Как я unlink собственная функция, в которой проверяются и рвутся исходящие связи. Как это реализовать?

    Правильно, при этом раскладе просто обнуляется связь на объект. И объект остается в свободном плавание.

    Щас приведу другой пример.
     
  20. mrsol

    mrsol Активный пользователь

    С нами с:
    26 мар 2007
    Сообщения:
    17
    Симпатии:
    0
    Вот пример с внутренней рекурсией. И с использованием register_tick_function. Создаеться первый объект в котором происходит регистрация функции. И пытаюсь сделать unset. Потом создаю второй объект и пытаюсь приравнять к NULL. Результат один и тот-же.

    PHP:
    1. <?php
    2.   class B{
    3.     private $child_class;
    4.     private $name;
    5.     private $memory;
    6.    
    7.     public function add_children(&$class, $counter){
    8.        
    9.         $t_counter = $counter;
    10.         echo "Add child class counter='".$counter."' \n";
    11.         if($counter<=0){
    12.             echo "Exit by counter\n";
    13.             return true;
    14.         }
    15.         $this->child_class = &$class;
    16.         $counter--;
    17.         $this->child_class->add_children($class, $counter);
    18.         echo "End add child class couner='".$t_counter."' \n";
    19.     }
    20.    
    21.     public function __construct($name, $count_child = 5){
    22.         $this->name = $name;
    23.         echo "Construct Class B name='".$this->name."'\n";
    24.         $this->add_children(&$this, $count_child);
    25.         register_tick_function('eche_ticks', $this->name);
    26.         declare(ticks=1);
    27.     }
    28.    
    29.     public function __destruct(){
    30.         echo "Desctruct class B name='".$this->name."'\n";
    31.         unregister_tick_function('eche_ticks');
    32.     }
    33.   }
    34.  
    35.   function eche_ticks($name){
    36.     ///to do somthing at each ticks
    37.     echo "---------------Ticks name='".$name."' \n";
    38.   }
    39.  
    40.   declare(ticks=1);
    41.   echo "Init \n";
    42.   $test_cl = new B('name_one', 1);
    43.   echo "Try unset\n";
    44.   unset($test_cl);
    45.   echo "Now variable is='".var_export($test_cl, true)."' \n";
    46.  
    47.   echo "Init \n";
    48.   $test_cl = new B('name_two', 1);
    49.   echo "Try NULL\n";
    50.   $test_cl = NULL;
    51.   echo "Now variable is='".var_export($test_cl, true)."' \n";
    52.  
    53.  
    54.   for($x=1; $x<=3; $x++){
    55.     echo "x='".$x."'\n";
    56.   }
    57.   echo "end script\n";
    58.  
    59. ?>
    Результат
    Код (Text):
    1. php -q test13.php
    2. Init
    3. Construct Class B name='name_one'
    4. Add child class counter='1'
    5. Add child class counter='0'
    6. Exit by counter
    7. End add child class couner='1'
    8. ---------------Ticks name='name_one'
    9. ---------------Ticks name='name_one'
    10. ---------------Ticks name='name_one'
    11. Try unset
    12. ---------------Ticks name='name_one'
    13. ---------------Ticks name='name_one'
    14. Now variable is='NULL'
    15. ---------------Ticks name='name_one'
    16. Init
    17. ---------------Ticks name='name_one'
    18. Construct Class B name='name_two'
    19. Add child class counter='1'
    20. Add child class counter='0'
    21. Exit by counter
    22. End add child class couner='1'
    23. ---------------Ticks name='name_one'
    24. ---------------Ticks name='name_two'
    25. ---------------Ticks name='name_two'
    26. ---------------Ticks name='name_one'
    27. ---------------Ticks name='name_one'
    28. ---------------Ticks name='name_two'
    29. ---------------Ticks name='name_two'
    30. ---------------Ticks name='name_one'
    31. ---------------Ticks name='name_one'
    32. ---------------Ticks name='name_two'
    33. ---------------Ticks name='name_two'
    34. ---------------Ticks name='name_one'
    35. Try NULL
    36. ---------------Ticks name='name_one'
    37. ---------------Ticks name='name_two'
    38. ---------------Ticks name='name_two'
    39. ---------------Ticks name='name_one'
    40. ---------------Ticks name='name_one'
    41. ---------------Ticks name='name_two'
    42. ---------------Ticks name='name_two'
    43. ---------------Ticks name='name_one'
    44. Now variable is='NULL'
    45. ---------------Ticks name='name_one'
    46. ---------------Ticks name='name_two'
    47. ---------------Ticks name='name_two'
    48. ---------------Ticks name='name_one'
    49. x='1'
    50. ---------------Ticks name='name_one'
    51. ---------------Ticks name='name_two'
    52. ---------------Ticks name='name_two'
    53. ---------------Ticks name='name_one'
    54. ---------------Ticks name='name_one'
    55. ---------------Ticks name='name_two'
    56. ---------------Ticks name='name_two'
    57. ---------------Ticks name='name_one'
    58. x='2'
    59. ---------------Ticks name='name_one'
    60. ---------------Ticks name='name_two'
    61. ---------------Ticks name='name_two'
    62. ---------------Ticks name='name_one'
    63. ---------------Ticks name='name_one'
    64. ---------------Ticks name='name_two'
    65. ---------------Ticks name='name_two'
    66. ---------------Ticks name='name_one'
    67. x='3'
    68. ---------------Ticks name='name_one'
    69. ---------------Ticks name='name_two'
    70. ---------------Ticks name='name_two'
    71. ---------------Ticks name='name_one'
    72. ---------------Ticks name='name_one'
    73. ---------------Ticks name='name_two'
    74. ---------------Ticks name='name_two'
    75. ---------------Ticks name='name_one'
    76. ---------------Ticks name='name_one'
    77. ---------------Ticks name='name_two'
    78. ---------------Ticks name='name_two'
    79. ---------------Ticks name='name_one'
    80. end script
    81. ---------------Ticks name='name_one'
    82. ---------------Ticks name='name_two'
    83. ---------------Ticks name='name_two'
    84. ---------------Ticks name='name_one'
    85. ---------------Ticks name='name_one'
    86. ---------------Ticks name='name_two'
    87. ---------------Ticks name='name_two'
    88. ---------------Ticks name='name_one'
    89. Desctruct class B name='name_one'
    90. ---------------Ticks name='name_one'
    91. ---------------Ticks name='name_two'
    92. ---------------Ticks name='name_two'
    93. ---------------Ticks name='name_one'
    94. ---------------Ticks name='name_two'
    95. Desctruct class B name='name_two'
    96. ---------------Ticks name='name_two'
    Тики всё равно идут. До конца скрипта.
    Если в строках 42 и 48
    $test_cl = new B('name_one', 1);
    и
    $test_cl = new B('name_two', 1);
    Заменить 1 на 0
    То получается следующий результат
    Код (Text):
    1. php -q test13.php
    2. Init
    3. Construct Class B name='name_one'
    4. Add child class counter='0'
    5. Exit by counter
    6. ---------------Ticks name='name_one'
    7. ---------------Ticks name='name_one'
    8. ---------------Ticks name='name_one'
    9. Try unset
    10. ---------------Ticks name='name_one'
    11. Desctruct class B name='name_one'
    12. ---------------Ticks name='name_one'
    13. Now variable is='NULL'
    14. Init
    15. Construct Class B name='name_two'
    16. Add child class counter='0'
    17. Exit by counter
    18. ---------------Ticks name='name_two'
    19. ---------------Ticks name='name_two'
    20. ---------------Ticks name='name_two'
    21. Try NULL
    22. ---------------Ticks name='name_two'
    23. Desctruct class B name='name_two'
    24. ---------------Ticks name='name_two'
    25. Now variable is='NULL'
    26. x='1'
    27. x='2'
    28. x='3'
    29. end script
    Как и должно было работать. И unset и NULL ведут себя идентично.
     
  21. mrsol

    mrsol Активный пользователь

    С нами с:
    26 мар 2007
    Сообщения:
    17
    Симпатии:
    0
    Поставим вопрос ребром.
    Как можно отследить из объекта, когда его передают по ссылке?
     
  22. Sergey89

    Sergey89 Активный пользователь

    С нами с:
    4 янв 2007
    Сообщения:
    4.796
    Симпатии:
    0
    Объект всегда передаётся по ссылке. Можно отследить только копирование.
     
  23. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    PHP:
    1. function unlink( ){
    2.   var $vars= get_object_vars( $this );
    3.   foreach( $vars as $name => &$val ) unset( $this->$name );
    4. }
    типа того