【问题标题】:Are there any instances when the destructor in PHP is NOT called?有没有没有调用 PHP 中的析构函数的情况?
【发布时间】:2011-03-26 22:39:45
【问题描述】:

这是我第一次在 stackoverflow 上发帖,但这些帖子对我帮助很大!

任何人,关于我的问题......是否有没有调用 PHP 中的析构函数的情况?我问的原因是因为我有一个映射器类,它将数据映射到对象,在构造函数中,我启动了一个事务,在析构函数中我将调用一个提交(我还有一个成员函数,它也可以执行提交,如有必要)。如果有任何情况下没有调用析构函数,我想知道这样我就可以预测它的发生并做出适当的计划。

非常感谢!

【问题讨论】:

    标签: php oop destructor


    【解决方案1】:
    • 根据manual,即使使用die()exit() 终止脚本,也会执行析构函数:

      即使使用 exit() 停止脚本执行,也会调用析构函数。在析构函数中调用 exit() 将阻止剩余的关闭例程执行。

    • 根据this SO question,当达到 PHP 的执行时间限制时,析构函数被执行(在 Apache 2 上确认,在 Windows 7 上确认 PHP 5.2)。

    • 当脚本因达到内存限制而终止时,析构函数也会执行。 (刚刚测试)

    • 析构函数确实在致命错误时执行(刚刚测试)更新:OP 无法确认这一点 - 似乎有致命错误,但情况有所不同

    • 它确实不会在解析错误时执行(因为不会解释整个脚本)

    • 如果服务器进程崩溃或发生其他 PHP 无法控制的异常,析构函数肯定不会执行。

    总而言之,它看起来很可靠。

    不过,除了在析构函数中进行清理之外,做其他事情的缺点是您的选择有些有限。你不能再抛出异常(除非你在析构函数中再次捕获它们),你不能输出任何错误消息,你不能再依赖其他对象(如数据库接口)的存在。 ....我在使用析构函数方面没有丰富的经验,但我不确定你打算做的是否是一个可行的想法。

    【讨论】:

    • 谢谢! :) 我从手册中看到了 sn-p,但我想我也会尝试在这里询问以确保安全。我刚刚测试了发生致命错误时发生了什么。我所做的只是创建了一个成员,该成员试图调用一个不存在的成员。没有调用析构函数。当然,它确实会在警告及以下情况下被调用。否则,我想不出任何其他可以检查它是否被调用的实例。我只是假设它确实并进行了广泛的测试!再次感谢!
    • @Logan 不客气。关于致命错误的有趣之处:当我使用$$fake(); 挑起一个错误时,它对我有用。也许这取决于错误的类型。另外,请查看我刚刚添加的段落以及对总体思路的一些想法。
    • 感谢您提供的额外信息!我只是测试了我是否可以在析构函数中做些什么。到目前为止,我知道我可以调用同一类的成员函数和不同类的成员函数(从构造函数实例化)。也许我可以做我想做的事,我会在确定后发表另一条评论。
    • 不同的致命错误在 PHP 中的处理方式不同。一些(例如失败的要求)甚至跳过关闭功能。如果发生致命错误,最好不要依赖任何确定性行为。此外,根据this bug report,启用 xdebug 后行为可能会发生变化(尽管在最近的 xdebug 版本中已修复)。
    • 如果你需要在 php 致命错误的情况下调用析构函数,然后在构造函数中将其注册为关闭处理程序:public function __construct() { register_shutdown_function(array($this, '__destruct')); }。这个解决方案的代价是对象引用(和对象本身)一直存在到 php 脚本执行结束。尽管如此,还是有一些情况是值得的 - 例如。在析构函数中删除巨大的 tmp 文件。
    【解决方案2】:

    我想补充一下,如果你在析构函数中出现致命错误,它可以阻止其他析构函数执行。

    【讨论】:

      猜你喜欢
      • 2012-09-17
      • 2019-10-05
      • 1970-01-01
      • 1970-01-01
      • 2011-11-23
      • 2015-12-23
      • 1970-01-01
      • 2017-11-18
      • 2013-12-22
      相关资源
      最近更新 更多