这周我遇到了一些小问题。前面的错误消息是关于:
[30-Dec-2012 15:19:32] PHP Fatal error: Exception thrown without a stack frame in Unknown on line 0
我认为这是因为我的错误处理程序(详细信息见下文)正在将任何错误转换为异常。如果没有堆栈框架,我可能应该阻止这种情况。
有没有一种简单的方法可以找出PHP中是否有堆栈帧?
Details:
在我的一个网站上,我运行了一个错误处理程序,它将每个错误转换为异常,常见的 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 问题(是的,这都是一些遗留问题,所以实际上这有点像鸭子胶带,我知道)。顺便说一句,这也非常有效。但是当我在新组件中犯了错误时却没有:
[30-Dec-2012 15:19:32] PHP Fatal error: Exception thrown without a stack frame in Unknown on line 0
这基本上是我的问题。有没有一种简单的方法可以防止出现这些错误?我有点知道为什么会出现这个错误,但我不太确定,所以我很难真正规避这个问题。我试图在脚本进入新的关闭阶段之前释放新的输出缓冲区,因为我认为这会导致这种情况。但这并没有成功。
最佳答案
您的问题表明您使用的是 EOL(生命周期结束)版本的 PHP(特别是 PHP < 5.3.0),这意味着它不再受支持。这个问题来自于在不存在 strack 框架的情况下抛出异常,因此旧引擎不知道如何正确处理这些异常。
这可能是由于几个不同的原因造成的。一些最常见的如下:
- 您从错误处理程序或异常处理程序内部引发了异常。
- 您从析构函数内部引发了异常。
- 您从回调内部引发了异常(例如输出缓冲回调函数)。
这是一个示例,演示了您在某些情况下遇到的问题...
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');
上面的代码会让您看到您在此处描述的 fatal error ...
ob_start("myCallBack");
...这里...
$foo = new foo;
此问题已在 PHP >= 5.3.0 中得到修复,因此如果您使用的是最新版本的 PHP,则不应看到此问题。
最简单的修复方法是升级 PHP。如果这不是一个选择,您必须考虑这些事实,即您不能在 PHP 不希望抛出异常的地方抛出异常(在回调函数、错误处理程序、异常处理程序等中......实际上都被认为是PHP 回调)。
另一件事是你不应该以这种方式将每个错误都变成异常。如果您正在做的事情正如我提供的代码所示(即从错误处理程序内部抛出异常 - 从而将每个错误变成异常),那么您将会给自己带来很多痛苦并且几乎没有任何好处。 PHP 错误不应该被处理。它们的目的是通知客户存在问题(客户是编写 PHP 代码的人)或潜在问题。处理错误本身并不像将每个错误都转换为异常然后处理该异常那么简单,因为并非每个错误都应该是异常的。例如,E_NOTICE 级别的错误在异常处理中没有地位。它们主要用于通知您可能存在错误,而不是您的代码一定存在错误,更不用说大多数错误甚至无法在用户空间代码中轻松处理(它们大多需要重新分解代码本身)。 我强烈建议不要这种糟糕的做法。
关于error-handling - 使用错误异常处理程序和关闭序列在没有堆栈帧的情况下防止异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14103727/