5

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

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

... // script goes on for a long

和....相比:

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

... // script goes on for a long

洞察任何人?

4

4 回答 4

3

感谢 PHP 4 的 Zend 引擎引入的引用计数系统,自动检测到不再引用它的资源,并被垃圾收集器释放。

考虑这一点的影响。可以安全地假设在垃圾回收之后变量的所有痕迹都消失了。换句话说,在 PHP 执行结束时,如果 PHP 仍然没有跟踪引用,它会如何关闭它?因此,当垃圾收集器吃掉它时它会关闭它似乎是相当合乎逻辑的。

这是一个糟糕的逻辑论点,因为它假定垃圾收集在取消设置后立即或不久发生,并且 PHP 不会保留对用户空间中不再存在的变量的隐藏引用。


如果 PHP 在超出范围时没有关闭文件句柄,那么一个更令人信服的案例可能是潜在的行为缺陷。考虑打开大量文件的某种守护进程。现在考虑是否永远不会调用 fclose。相反,允许变量超出范围或在它们上显式调用 unset。

如果这些文件句柄没有关闭,这个长时间运行的守护进程将耗尽文件句柄。


潜在行为特定的测试脚本:

<?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 源代码以获得确凿的证据

于 2012-06-07T09:36:06.480 回答
2

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秒内运行两次脚本;如果您“仍处于锁定状态”,则显然取消手柄并没有释放锁定。在我的测试中,我没有得到“仍然锁定”,因此显然取消设置句柄至少会释放锁定,尽管在垃圾收集时释放锁定但不关闭文件似乎很愚蠢。

于 2012-06-07T09:15:28.210 回答
1

unset($handle)将破坏$handle变量,但不会关闭 . 指向的文件$handle。您仍然需要调用fclose()以关闭文件。

于 2012-06-07T09:19:20.020 回答
0

一些研究:

fclose使$handle之成为resource(5) of type (Unknown)

unset成功了NULL

并且在fclosephp 消耗更多的 88 字节内存之后。

所以:他们是不同的=)

于 2012-06-07T09:20:06.887 回答