Могу ли я закрыть файл, сняв ручку?

Я немного озадачен, если смогу сэкономитьfclose команда просто сбросив переменную, которая несет дескриптор?

$handle = fopen($file);
...
fclose($handle);

... // script goes on for a long

По сравнению с:

$handle = fopen($file);
...
unset($handle);

... // script goes on for a long

Кто-нибудь прозрения?

 Nanne07 июн. 2012 г., 11:18
Просто любопытно: по какой причине вы бы выбралиunset вышеfclose?
 hakre07 июн. 2012 г., 11:23
@SanjaySurani: Это только доказательство того, что ваш двоичный файл W2K PHP сломан и ничего более.is_respource должен всегда возвращатьсяTRUE если$fp это ресурс. Лучше проверьте, успешно ли вы открыли файл.
 Pekka 웃07 июн. 2012 г., 11:16
Я бы не стал доверять тому, чтобы он работал последовательно в разных операционных системах (хотя это просто внутреннее чувство; у меня нет никаких доказательств в любом случае)
 Sanjay07 июн. 2012 г., 11:19
Пекка прав, я пыталсяecho '$fp is resource = '.(is_resource($fp) ? 'true': 'false'); Он возвращает false на W2K-машине, а в других возвращает true
 Sanjay07 июн. 2012 г., 11:31
@hakre, да, возможно, вы правы, но я использовал fclose для обоих, и мне было интересно, почему это отличается. Спасибо за ваш комментарий

Ответы на вопрос(4)

Документы PHP намекают на то, что все ресурсы без оставшихся ссылок «освобождены», я предполагаю, что для файловых дескрипторов это будет включать закрытие файла.

Простой тестовый пример:

$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 секунд; если вы «все еще заблокированы», то, очевидно, снятие ручки не сняло блокировку. В моем тесте я сделалnot получить "все еще заблокирован", поэтому, очевидно, сбросив дескрипторat least снимает блокировку, хотя было бы глупо снимать блокировки при сборке мусора, но не закрывать файл.

 hakre07 июн. 2012 г., 11:21
Где PHP документы намекают на это? Вы можете предоставить гиперссылку?
 07 июн. 2012 г., 11:22
Resources, раздел "Освобождение ресурсов"
 07 июн. 2012 г., 11:24
Документы не говорят, но нет никакого смысла не делать этого.
 hakre07 июн. 2012 г., 11:24
Разве освобождение ресурса в PHP закроет дескриптор файла?
 07 июн. 2012 г., 11:37
Смотрите обновленный ответ для теста.

Thanks to the reference-counting system introduced with PHP 4's Zend Engine, a resource with no more references to it is detected automatically, and it is freed by the garbage collector.

Примите во внимание последствия этого. Можно с уверенностью предположить, что все следы переменной исчезли после сборки мусора. Другими словами, в конце выполнения 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
}

И в Windows 7, и в Debian 6 соединение было закрыто после сброса.

Очевидно, однако, это только доказывает, что на моих конкретных машинах с моей конкретной версией PHP это будет работать. Не имеет никакого значения для файловых дескрипторов или тому подобного :).

Am searching the PHP source now for hard proof

 07 июн. 2012 г., 11:39
& quot; Не имеет никакого значения для файловых дескрипторов или тому подобного:). & quot; Да ... Я сейчас пытаюсь следовать коду через путь сборки мусора / забивания ресурсов.
 07 июн. 2012 г., 11:39
Сокеты не обязательно обрабатываются так же, как обычные файлы. Не имеет смысла обращаться по-другому, но PHP часто не имеет смысла.

unset($handle) уничтожит$handle переменная, но она не закроет файл, на который указывает$handle, Вам все еще нужно позвонитьfclose() закрыть файл.

 07 июн. 2012 г., 11:23
@hakre Я имею в виду использованиеfclose($handle) и неunset($handle).
 hakre07 июн. 2012 г., 11:20
Мне трудно доказать, что, потому что после снятия ручки я не могу использоватьfclose() еще не так ли?
 hakre07 июн. 2012 г., 11:24
Очевидно, но я обеспокоен рассуждениями, а не тем, что лучше.

некоторые исследования:

fclose марки$handle бытьresource(5) of type (Unknown) в то время как

unset делает этоNULL.

и послеfclose php потребляет на 88 байт памяти больше.

итак: они разные =)

 hakre07 июн. 2012 г., 11:21
Используя память, чтобы проверить это. Я бы сказал, что это интересно, но это требует дополнительной проработки, чтобы вы могли устранить побочные эффекты, которые можно себе представить.
 19 июл. 2013 г., 18:58
unset делает этоUndefinedнеNULL.
 07 июн. 2012 г., 11:24
я использовалmemory_get_usage() чтобы получить это

Ваш ответ на вопрос