防止没有堆栈框架的异常与错误异常处理程序和关闭序列 [英] Preventing Exceptions without Stack Frames with Error Exception Handler and Shutdown Sequences

查看:119
本文介绍了防止没有堆栈框架的异常与错误异常处理程序和关闭序列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一周内遇到了一些小问题。前面提到的错误消息是:


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


我认为这是因为我的错误处理程序(详见下文)将任何错误转换为例外。我可能应该防止这种情况,如果没有堆栈框架。



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


详细信息:


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



我之前介绍过,因为该网站主要是旧代码,我想有任何问题导致异常,我终于可以以流线化的方式捕获一个异常处理程序,并请求停止。



我把它放在自己的类中,处理程序被注册,并且并行地打开输出缓冲区以捕获输出,直到异常被抛出。基本代码如下:

  //注册输出缓冲
$ r = ob_start(array($ this,'handleBuffer ));

//注册错误处理程序
$ this-> _originalErrorHandler = set_error_handler(array($ this,'handleError'));

//注册异常处理程序
$ this-> _originalExceptionHandler = set_exception_handler(array($ this,'handleException'));

这个工作非常好,直到我决定在混合中添加另一个输出缓冲类。只有一个捕捉到所有的输出,然后可以做一些后期制作在网站上,包括检查HTML问题(是的,这是一切遗产,实际上这是一个鸭嘴豆,我知道)。这也是非常好的btw。但是,当我在新组件中出错时,不是这样:


[2012年12月30日15:19:32] PHP致命错误:在没有堆栈框架的情况下抛出异常0行


这基本上是我的问题。有没有办法避免得到这些错误?我有些知道为什么错误是给出的,但我不完全确定,所以我很难真正规避这个问题。我尝试在之前发布新的输出缓冲区脚本进入新的关闭阶段,因为我认为这将导致这种情况。但是这并没有这样做。

解决方案

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



这可能是由于一对夫妇有不同的原因一些最常见的例子如下:


  1. 你从错误处理程序或异常处理程序内部抛出一个异常。 b $ b
  2. 你从一个析构函数里面抛出一个异常。

  3. 你从回调中抛出一个异常(像输出缓冲回调函数)。

这是一个例子,在一些情况下演示了你的问题...

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

函数myExceptionHandler($ exception){
echo我们得到一个异常消息:'{$ exception-> getMessage()}';
}

函数myCallBack($ contents){
trigger_error('ohnoes!'); //您不能在旧版本的PHP< 5.3
}

class Foo {
public function __destruct(){
trigger_error('ohnoes!'); //您不能在旧版本的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级错误在异常处理中没有任何地位。它们主要用于通知您潜在的错误,而不是您的代码一定会有bug,更不用说大多数用户空间代码中的大部分都不能轻松处理(他们大多需要重新启动,代码本身)。 我强烈反对这种不良做法


I've run over a somewhat little problem over the week. The error message upfront this is about:

[30-Dec-2012 15:19:32] PHP Fatal error: Exception thrown without a stack frame in Unknown on line 0

I think it is because my error handler (see below for details) is turning any error into an exception. I might should prevent that in case there is no stack frame.

Is there an easy way to find out if there is any stack frame or not in PHP?

Details:

On one of my websites I've got an error handler running that is turning every error into an exception, the common ErrorException to be precise.

I introduced it some time ago because the site is mainly legacy code and I wanted to have any issue result in an exception I can finally "catch" in a streamlined fashion an exception handler and give the request a stop.

I put this into class of it's own, the handler is registered and also in parallel an output buffer is opened to catch the output up until the exception is thrown. Basically code like this:

// 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'));

This worked all fine and dandy until I decided to add another output buffering class into the mix. Just one that catches as well all output and then can do some "post production" on the website, including checking for HTML problems (yes, it's all a bit legacy so actually this is a bit duck-taped, I know). That also worked very fine btw. however not when I made a mistake in the new component:

[30-Dec-2012 15:19:32] PHP Fatal error: Exception thrown without a stack frame in Unknown on line 0

This is basically my problem. Is there an easy way to prevent getting these errors? I somewhat know why the error is given but I'm not so entirely sure so it's hard for me to really circumvent the problem. I tried to release the new output buffer before the script enters the new shutdown phase because I thought this would cause this. But this didn't make it.

解决方案

Your problem indicates that you are using an EOL (End Of Life) version of PHP (specifically PHP < 5.3.0), which means it's no longer supported. This issue comes from throwing an exception where no strack frame exists and as such the old engine did not know how to handle those exceptions properly.

This can be due to a couple of different reasons. Some of the most common ones are as follows:

  1. You threw an exception from inside an error handler or exception handler.
  2. You threw an exception from inside a destructor.
  3. You threw an exception from inside a callback (like an output buffering callback function).

Here's an example that demonstrates your problem under some of those circumstances...

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');

The above code would cause you to see the fatal error you described here...

ob_start("myCallBack");

... and here...

$foo = new foo;

This problem has been fixed in PHP >= 5.3.0 so you should not see this issue if you were using the most current version of PHP.

The simplest fix is to upgrade your PHP. If that is not an option you must consider these facts that you can not throw exceptions where PHP does not expect them to be thrown (in callback functions, error handlers, exceptions handlers, etc... -- which are actually all considered to be callbacks to PHP).

The other thing is you should not be turning every error into an exception in this way. If what you are doing is as the code I supplied demonstrates (i.e. throwing an exception from inside the error handler -- thus turning every error into an exception) then you are going to cause yourself a lot of pain and with virtually no benefit. PHP errors are not meant to be handled. They are meant to inform the client of a problem (the client being the person writing the PHP code), or potential problem. Handling the error itself is not as simple as turning every error into an exception and then handling that exception, because not every error should be exceptional. For instance, E_NOTICE level errors have no place in exception handling. They are primarily used to notify you of a potential for a bug, not that there is necessarily something buggy with your code and not to mention that most of them can't even be handled easily in user-space code (they mostly require re-factoring the code itself). I strongly advice against this poor practice.

这篇关于防止没有堆栈框架的异常与错误异常处理程序和关闭序列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆