析构函数中抛出异常的问题

3

我找不到可靠的来源来确保我能在 __destruct() 中抛出异常。

这是 PHP 文档中的说明:

试图从析构函数(在脚本终止时调用)中抛出异常会导致致命错误。

但是当我测试时:

class A 
{
    public function __destruct()
    {
       throw new \Exception();
    }
}

try {
    $a = new A();

} catch(\Exception $x) {
    var_dump($x);
}

看起来这不是真的。我通常可以抛出和捕获异常。那么,为什么文档上有这一行呢?

在Mark Baker的回答后编辑:

实际上它是有效的,析构函数可以抛出并捕获异常。我仍然不确定为什么文档会撒谎。


1
析构函数在你的示例代码中根本没有被调用;尝试取消设置 $a,它会抛出异常。 - Mark Baker
1
否则,当脚本终止时会抛出异常;但这超出了您的try/catch范围。 - Mark Baker
“called in the time of script termination” 是提示。 - Nigel Ren
@MarkBaker 我怎么会错过那个... 你说得完全正确。所以,在析构函数中抛出的异常是无法被捕获的。 - hvertous
@MarkBaker,您能否将其发布为答案,以便我能够接受它? - hvertous
1个回答

6

在您的脚本中没有任何地方调用析构函数,因此您的try/catch块将无法捕获任何异常。如果您在try / catch块内使用unset($x),那么将会引发一个异常并被正确捕获。

class A {
    public function __destruct() {
       throw new \Exception();
    }
}

try {
    $a = new A();
    unset($a);
} catch(\Exception $x) {
    var_dump($x);
}

否则,PHP在脚本终止时会抛出异常,但这在您的try/catch块之外。 编辑 如果您的对象没有被手动销毁,则在脚本终止时抛出的异常无法捕获,因为您无法将try/catch包装在PHP的内部终止处理周围,该处理会销毁对象;这就是导致致命错误的原因。

致命错误:未捕获的异常

所以这就是文档警告您的内容。

我测试过了,它可以工作。谢谢。但是为什么文档会撒谎呢? - hvertous
如果您执行我发布的代码,则可以捕获当 $a 未设置时抛出的异常,并进行 var dump Demo - Mark Baker
你说得对,我编辑了我的评论但不够快,抱歉。 - hvertous
2
文档并没有说谎……它只是指出当对象在脚本终止时被销毁时抛出的异常无法被捕获,因此会导致“致命错误:未捕获的异常”- 演示 - Mark Baker
Mark Bakes,补充一下你的话,似乎连set_exception_handler也无法“捕获”在脚本终止时抛出的异常,因为我遇到了这个问题,在这里我找到了解释。 - mikl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接