2

私は一週間で少し問題にぶつかりました。これに関するエラーメッセージは次のとおりです。

[30-Dec-2012 15:19:32] PHPの致命的なエラー:0行目の不明でスタックフレームなしで例外がスローされました

私のエラーハンドラー(詳細は以下を参照)がエラーを例外に変えているためだと思います。スタックフレームがない場合は、それを防ぐ必要があるかもしれません。

PHPにスタックフレームがあるかどうかを確認する簡単な方法はありますか?

詳細:

私のWebサイトの1つで、すべてのエラーを例外に変換するエラーハンドラーを実行しています。これは、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の問題のチェックを含め、Webサイトで「ポストプロダクション」を実行できるのは1つだけです(はい、それはすべて少しレガシーなので、実際には少しダックテープです)。それも非常にうまくいきました。ただし、新しいコンポーネントを間違えたときはそうではありません。

[30-Dec-2012 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 へのコールバック)。

もう 1 つは、この方法ですべてのエラーを例外に変えてはならないということです。あなたが行っていることが、私が提供したコードが示すとおりである場合 (つまり、エラー ハンドラー内から例外をスローし、すべてのエラーを例外に変える) 、多くの苦痛を与え、事実上何のメリットもありません。PHP エラーは、処理するためのものではありません。クライアントに問題を通知するためのものです (クライアントは PHP コードを書いている人です)。)、または潜在的な問題。エラー自体の処理は、すべてのエラーを例外に変えてからその例外を処理するほど単純ではありません。すべてのエラーが例外的であるべきではないからです。たとえば、E_NOTICE レベルのエラーは例外処理の対象外です。それらは主にバグの可能性を通知するために使用されます。コードにバグがあるとは限りません。また、それらのほとんどはユーザー空間コードで簡単に処理することさえできないことは言うまでもありません (ほとんどの場合、再インストールが必要です)。コード自体を因数分解します)。私は、このお粗末な慣行に反対することを強くお勧めします。

于 2012-12-31T17:25:34.873 に答える