![]() |
|
Модераторы: skyboy, MoLeX, Aliance, ksnk |
![]()
|
|
| skyboy |
|
||||||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 75 Всего: 260 |
чем меньше знаешь - тем радостнее жить: что ни день - Великое открытие
создавая дерево на основе линейного массива столкнулся с ситуацией, когда из исходного массива "пропадал" элемент. Так как у меня все-то кода было - несколько foreach-циклов с использованием ссылок и без, а все присвоение шло внутри элементов массива, заподозрил неладное. в мане среди коментариев к foreach наткнулся на(малость добавил вывода для полноты картины):
код выводит(жирным выделен исходный массив):
видно, что в массиве без присвоений и явного использования ссылок происходит модификация массива. происходит это вследствие того, что после последней итерации первого цикла, в переменной $month осталось значением ссылка на последний элемент массива $months: $month = &$months[2]; следовательно, при каждой итерации второго цикла, очередной элемент массива $months будет связан не просто с именем "$month", а с тем, на что это имя ссылается - последний элемент исходного массива. И с каждой итерацией второго цикла, последний элемент исходного массива будет изменяться и изменяться. В основном теле статьи есть предупреждение:
Так что зря я сразу в коменты полез, надо было до конца дочитать. Зачем пишу, раз в мануале есть? Во-первых, мне поначалу такое поведение показалось неожиданным настолько, что стал искать у себя алгоритмическую ошибку. Во-вторых, сам в чужом коде встречал массив с использованием ссылок, но нигде после цикла не попадалось на глаза unset. Надеюсь, кого-то просветит. |
||||||
|
|||||||
| solenko |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1473 Регистрация: 15.1.2006 Где: Украина Репутация: 34 Всего: 67 |
Кстати, этот пример рассматривается в Zend Certification Guide. Тоже долго смотрел на результат выполнения. ))
-------------------- Ла-ла-ла-ла Заметьте, нет официального подтверждения, что это не просто четыре слога. |
|||
|
||||
| SamDark |
|
|||
|
Добрый кот ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 1424 Регистрация: 25.7.2006 Где: Voronezh Репутация: 10 Всего: 38 |
Я тоже сталкивался: http://rmcreative.ru/blog/post/iteratsija-...enija-po-ssylke
-------------------- rmcreative.ru — Это жжж неспроста... yiiframework.ru — О фреймворке Yii на русском. reggi — здесь я регистрирую домены |
|||
|
||||
| sTa1kEr |
|
|||
|
9/10 программиста ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1553 Регистрация: 21.2.2007 Репутация: 56 Всего: 146 |
А это бесполезно Тут я писал в свое время чем опасны эмперсанды и зачем надо делать unset в конце цикла. А почему так происходит можно узнать прочитав статью Дерика Ретанса о ссылках в PHP. Это еще одна причина почему стоит для дампа переменных использовать функцию var_dump(), а не всякие print_r'ы и var_export'ы. Это сообщение отредактировал(а) sTa1kEr - 25.1.2010, 20:42 |
|||
|
||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 75 Всего: 260 |
прости, но не мог бы ты объяснить, что именно ты имеешь в виду? то, что в выдаче print_r никак не указываются ссылки, а выводятся значения? за ссылки спасибо, да. статью касательно ссылок встречал уже, но тут меня удивило другое: я находил логичным обнулять счетчик цикла, а не работать как с ссылкой. не могу представить, где и как может быть задействован этот механизм. вот после цикла оставлять значение счетчика или последнего элемента полезно - ведь внутри цикла может быть вызван break и в вспомогательной переменной должен быть совсем не последний элемент, да. Добавлено @ 22:34 что-то я не то читаю, раз раньше не натыкался. |
|||
|
||||
| Simpliest |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 625 Регистрация: 1.9.2009 Репутация: 1 Всего: 3 |
skyboy, рекомендую покопать еще деструкторы у классов и последовательность их вызова при завершении скрипта
О сколько нам открытий чудных, готовит просвещенья дух Я, кстати, так и не нашел способа однозначно убить все ссылки на объект |
|||
|
||||
| sTa1kEr |
|
|||
|
9/10 программиста ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1553 Регистрация: 21.2.2007 Репутация: 56 Всего: 146 |
||||
|
||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 75 Всего: 260 |
ну, открытий много, но не все они кажутся мне нелогичными/неожиданными наверное, плохо я копал, раз нашел только тот факт, что унаследованные деструкторы(так же, как и конструкторы) не вызываются автоматически и должны быть вызваны явно. и что деструктор нормально вызывается уже после отправки данных пользователю. я не в ту сторону начал рыть? |
|||
|
||||
| Simpliest |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 625 Регистрация: 1.9.2009 Репутация: 1 Всего: 3 |
В ту |
|||
|
||||
| sTa1kEr |
|
|||
|
9/10 программиста ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1553 Регистрация: 21.2.2007 Репутация: 56 Всего: 146 |
Кстати, это тоже не совсем так Причина такого поведения, я думаю, заключается в самой архитектуре cgi интерфейса. А именно в том, что пока воркер веб сервера не дождется завершения php-cgi процесса, он будет ждать от него данные и при этом ему не известно, да и не важно, что происходит в php-cgi и в какой стадии находится скрипт. Однако это только мои домыслы, пруфлинка у меня нет. Это сообщение отредактировал(а) sTa1kEr - 26.1.2010, 11:10 |
|||
|
||||
| skyboy |
|
||||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 75 Всего: 260 |
ясно. спасибо. интересно. скопирую обсуждаемый код сюда:
также интересно: 0. деструктор $b1 вызывается, но данные объекта(поле $b->b) доступно и после вызова деструктора. для меня это тоже было удивительно. 1. если вместо exit/die использовать throw new Exception(), вызов деструкторов "встанет на свои места". |
||||
|
|||||
| solenko |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1473 Регистрация: 15.1.2006 Где: Украина Репутация: 34 Всего: 67 |
0.
Collecting Cycles
Насколько я понимаю, именно это и происходит. Хотя, возможно, в режиме "завершения" сборщик мусора просто игнорирует refcount и вызывает деструкторы для ненулевых. Поведение, естественно, некорректное, но и exit/die некорректный способ завершения скрипта. Вобщем, "будь осторожен, следи за собой" и грабель станет меньше ) 1. Тут то как раз все понятно. Если вы используете throw (или просто return), то функция завершается корректно и удаляется локальная переменная $a1 а не все скопом. -------------------- Ла-ла-ла-ла Заметьте, нет официального подтверждения, что это не просто четыре слога. |
|||
|
||||
| sTa1kEr |
|
|||
|
9/10 программиста ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1553 Регистрация: 21.2.2007 Репутация: 56 Всего: 146 |
А в чем собственно проблема с деструкторами? Порядок их вызова после завершения работы скрипта? Да и черт с ним, в PHP он не важен.
|
|||
|
||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 75 Всего: 260 |
sTa1kEr, ну, не сказал бы. По ссылке, приведенной Simpliest, обсуждается ситуация, когда в деструкторе идет работа с БД через mysqli. Если деструктор mysqli объекта будет вызван раньше, чем деструктор остальных, то подключение к базе окажется закрытым. Если я правильно понял.
|
|||
|
||||
| sTa1kEr |
|
|||
|
9/10 программиста ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1553 Регистрация: 21.2.2007 Репутация: 56 Всего: 146 |
Shutdown function полностью решает эту проблему. Да и зачем вообще работать с базой в деструкторе, можно реальный пример, а не высосанный из пальца?
Добавлено через 6 минут и 41 секунду Если использовать деструкторы по назначению, а именно для очистки/уничтожения за собой мусора и не закрытых хендлеров, то никаких проблем не будет. |
|||
|
||||
![]()
|
| Правила форума "PHP" | |
|
|
Новичкам:
Важно:
Внимание:
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | PHP: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |