我可以通过取消设置句柄来关闭文件吗?


Can I close a file by unsetting the handle?

如果我可以通过取消设置带有句柄的变量来节省fclose命令,我有点困惑?

$handle = fopen($file);
...
fclose($handle);
... // script goes on for a long

相比:

$handle = fopen($file);
...
unset($handle);
... // script goes on for a long

有人有见解吗?

由于 PHP 4 的 Zend Engine 引入了引用计数系统,自动检测不再引用的资源,并由垃圾回收器释放。

考虑一下这的影响。 可以安全地假设变量的所有痕迹在垃圾回收后都消失了。 换句话说,在 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 版本可以工作。 在文件句柄或类似:)上没有任何意义。


现在正在搜索PHP源代码以寻找硬证据

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 秒内运行脚本两次;如果您被"仍然锁定",那么显然取消设置手柄并没有释放锁。在我的测试中,我没有"仍然锁定",所以显然取消设置句柄至少释放了锁,尽管在垃圾收集时释放锁但不关闭文件似乎很愚蠢。

unset($handle)将销毁$handle变量,但它不会关闭$handle指向的文件。您仍然需要调用fclose()来关闭文件。

一些研究:

fclose使$handle变得resource(5) of type (Unknown)

unset使它NULL.

fclose之后,PHP 会消耗 88 字节的内存。

所以:它们是不同的=)

相关文章: