2

这一周我遇到了一个小问题。前面的错误消息是关于:

[2012 年 12 月 30 日 15:19:32] PHP 致命错误:在第 0 行的未知中抛出没有堆栈帧的异常

我认为这是因为我的错误处理程序(详见下文)正在将任何错误变成异常。如果没有堆栈框架,我可能应该阻止这种情况。

有没有一种简单的方法可以找出 PHP 中是否有任何堆栈框架?

细节:

在我的一个网站上,我运行了一个错误处理程序,它将每个错误都变成异常,ErrorException准确地说是常见的。

我前段时间介绍了它,因为该站点主要是遗留代码,我希望有任何问题导致异常,我最终可以以简化的方式“捕获”异常处理程序并停止请求。

我把它放到它自己的类中,注册处理程序,同时打开一个输出缓冲区来捕获输出,直到抛出异常。基本上是这样的代码:

// register output buffering
$r = ob_start(array($this, 'handleBuffer'));

// register error handler       
$this->_originalErrorHandler = set_error_handler(array($this, 'handleError'));

// register exception handler
$this->_originalExceptionHandler = set_exception_handler(array($this, 'handleException'));

直到我决定在混合中添加另一个输出缓冲类之前,这一切都很好。只有一个能够捕获所有输出,然后可以在网站上进行一些“后期制作”,包括检查 HTML 问题(是的,这都有点遗留,所以实际上这有点老套,我知道)。顺便说一句,这也很好用。但是当我在新组件中犯了一个错误时:

[2012 年 12 月 30 日 15:19:32] PHP 致命错误:在第 0 行的未知中抛出没有堆栈帧的异常

这基本上是我的问题。有没有一种简单的方法可以防止出现这些错误?我有点知道为什么会出现错误,但我不太确定,所以我很难真正规避这个问题。我试图在脚本进入新的关闭阶段之前释放新的输出缓冲区,因为我认为这会导致这种情况。但这并没有成功。

4

1 回答 1

3

您的问题表明您正在使用 PHP 的EOL ( End Of Life ) 版本(特别是 PHP < 5.3.0),这意味着它不再受支持。这个问题来自抛出一个不存在 strack 框架的异常,因此旧引擎不知道如何正确处理这些异常。

这可能是由于几个不同的原因。一些最常见的如下:

  1. 您从错误处理程序或异常处理程序内部引发了异常。
  2. 您从析构函数内部抛出了异常。
  3. 您从回调内部抛出异常(如输出缓冲回调函数)。

这是一个示例,可以在某些情况下演示您的问题...

function myErrorHandler($errno, $errstr, $errfile, $errline)
{
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}

function myExceptionHandler($exception) {
    echo "We got an exception with message: '{$exception->getMessage()}'";
}

function myCallBack($contents) {
    trigger_error('ohnoes!'); // You can't throw an error from the output buffer callback function in older versions of PHP < 5.3
}

class Foo {
    public function __destruct() {
        trigger_error('ohnoes!'); // You can't throw an error from a destructor in older versions of PHP < 5.3
    }
}

set_error_handler('myErrorHandler');
set_exception_handler('myExceptionHandler');

上面的代码会导致您看到您在此处描述的致命错误...

ob_start("myCallBack");

... 和这里...

$foo = new foo;

此问题已在 PHP >= 5.3.0 中修复,因此如果您使用的是最新版本的 PHP,则不会看到此问题。

最简单的解决方法是升级您的 PHP。如果这不是一个选项,您必须考虑这些事实,即您不能在 PHP 不期望它们被抛出的地方抛出异常(在回调函数、错误处理程序、异常处理程序等中...... - 实际上所有这些都被认为是回调到 PHP)。

另一件事是您不应该以这种方式将每个错误都变成异常。如果您正在做的事情正如我提供的代码所演示的那样(即从错误处理程序内部抛出异常 - 从而将每个错误都变成异常),那么您将给自己带来很多痛苦并且几乎没有任何好处。PHP 错误不应该被处理。它们旨在通知客户问题(客户是编写 PHP 代码的人) 或潜在问题。处理错误本身并不像将每个错误都变成异常然后处理该异常那么简单,因为并非每个错误都应该是异常的。例如,E_NOTICE 级别的错误在异常处理中没有位置。它们主要用于通知您潜在的错误,而不是您的代码一定有错误,更不用说它们中的大多数甚至无法在用户空间代码中轻松处理(它们大多需要重新分解代码本身)。我强烈反对这种糟糕的做法

于 2012-12-31T17:25:34.873 回答