Я немного озадачен, если могу сэкономить команду fclose
, просто отключив переменную, которая несет ручку?
$handle = fopen($file); ... fclose($handle); ... // script goes on for a long
По сравнению с:
$handle = fopen($file); ... unset($handle); ... // script goes on for a long
с$handle = fopen($file); ... unset($handle); ... // script goes on for a long
Кто-нибудь знает?
Благодаря системе подсчета ссылок, представленной с Zend Engine PHP 4, ресурс, не имеющий больше ссылок на него, автоматически обнаруживается, и он освобождается сборщиком мусора.
Подумайте о последствиях этого. Можно с уверенностью предположить, что все следы переменной исчезли после сбора мусора. Другими словами, в конце выполнения PHP, если PHP еще не отслеживает ссылку, как ее закрыть? Таким образом, кажется довольно логичным, что он закроет его, когда сборщик мусора съест его.
Это плохой логический аргумент, хотя, поскольку он предполагает, что сборка мусора происходит либо сразу, либо вскоре после отмены, и что PHP не содержит скрытых ссылок на переменные, которые больше не существуют на земле пользователя.
Более убедительный случай может быть потенциальным поведенческим недостатком, если PHP не закрывает дескрипторы файлов, когда они выходят за рамки. Рассмотрим какой-то демон, который открывает много файлов. Теперь рассмотрим, не вызывает ли fclose. Вместо этого переменным разрешено выходить из области видимости или отменять их явно.
Если эти дескрипторы файлов не были закрыты, на этом длинном запуске демона закончились бы дескрипторы файлов.
Потенциально специфический сценарий тестирования:
<?php $db = mysql_connect(...); if ($db) { echo "Connected\n"; sleep(5); //netstat during this just for paranoia unset($db); echo "Unset\n"; sleep(5); //netstat during this and the connection is closed }
с<?php $db = mysql_connect(...); if ($db) { echo "Connected\n"; sleep(5); //netstat during this just for paranoia unset($db); echo "Unset\n"; sleep(5); //netstat during this and the connection is closed }
Как на Windows 7, так и на Debian 6 соединение закрывается после отмены.
Очевидно, однако, это только доказывает, что на моих конкретных машинах с моей конкретной версией PHP эта работа будет работать. Не имеет значения для дескрипторов файлов и т.п. :).
Теперь я ищу источник PHP для жестких доказательств
PHP docs подсказывают, что все ресурсы без оставшихся ссылок «освобождаются», я предполагаю, что для дескрипторов файлов это будет закрытие файла.
Простой тестовый пример:
$f = fopen("test.php", "r"); if (!flock($f, LOCK_EX)) { print("still locked\n"); exit; } unset($f); sleep(5); print("goodbye\n");
с$f = fopen("test.php", "r"); if (!flock($f, LOCK_EX)) { print("still locked\n"); exit; } unset($f); sleep(5); print("goodbye\n");
(Я сохранил это как test.php
, поэтому он сам блокируется, возможно, потребуется изменить имя файла в fopen()
для какого-либо существующего файла в противном случае)
Запускайте скрипт дважды в течение 5 секунд; если вы «все еще заблокированы», то, по-видимому, сбрасывание ручки не освобождает замок. В моем тесте я не получил «все еще заблокирован», поэтому, по-видимому, отключение дескриптора по крайней мере освобождает блокировку, хотя было бы глупо выпускать блокировки при сборке мусора, но не закрывать файл.
unset($handle)
уничтожит переменную $handle
, но она не будет закрывать файл, на который указывает $handle
. Вам все равно нужно вызвать fclose()
чтобы закрыть файл.
некоторые исследования:
fclose
заставляет $handle
быть resource(5) of type (Unknown)
тогда как
unset
делает его NULL
.
и после того, как fclose
php потребляет 88 байт памяти больше.
так: они разные =)