35

エラーの一般的な理由の1つは、例外ハンドラー内から例外がスローされることです。これは、デバッグしようとしているアプリケーションでは発生しないと確信しています...しかし、すべての初期化処理行を、try/catchのindex.phpの先頭に配置しました。*

これは、セッションに格納するためにシリアル化できないもの もあるため、明らかに発生する可能性があります。せいぜいこのアプリケーションは配列をセッションに格納しますが(かなり)、通常とは異なるものは何も格納しないと確信しています。

主キーがINT(11)ではなくCHAR(32)である必要があるため、誰かがそれが起こったとコメントしました。このアプリのPKはすべてINTです。

他の提案は、5.3.6で修正されたPHP 5.3.3フルディスク、およびSimpleXML値を型キャストする必要がある場合に問題になる可能性があることです。たまたまPHP5.3.3を実行していますが、この場合、アップグレードは最後の手段である必要があります。いつもそうしているわけではありません。

更新/注:実際にはエラーを自分で再現することはできません。ログでエラーが発生していることを確認するだけです。エラーが発生していると思われる場所については、以下の段落を参照してください...

*エラーログから、発生している場所の少なくとも1つはindex.phpである可能性があります。一部のエントリで参照URLで示されているため、これを推測しています。try / catchコードは現在、スクリプトの「最上位」の初期化部分の周りにのみあり、その下は主にHTML出力です。出力にはいくつかのPHPコードが含まれているので(かなり単純なものですが)、それをテストする必要があるかもしれません。これがcatch部分で、ログに出力を生成していません。

} catch (Exception $e) {
    error_log(get_class($e)." thrown. Message: ".$e->getMessage(). "  in " . $e->getFile() . " on line ".$e->getLine());
    error_log('Exception trace stack: ' . print_r($e->getTrace(),1));
}

これに関するヒントを本当にいただければ幸いです。

編集:PHPはApacheモジュールとして実行されています(サーバーAPI:Apache 2.0ハンドラー)。PHPアクセラレーターが使用されているとは思いませんが、わかり方がわからない可能性があります。ウィキペディアにリストされているものはどれもphpinfo()にありません。

私が知る限り、MPMはプリフォークです。これは私がMPMを調べた最初のものです。

# ./httpd -l
Compiled in modules:
  core.c
  prefork.c
  http_core.c
  mod_so.c
4

12 に答える 12

19

問題

要するに、どこかで例外がスローされ、どこで今までエラーを再現できなかったのかわかりません。これは一部の人にのみ発生し、あなたには発生しません。エラーログに表示されるので、他の人にも発生することがわかります。

問題を再現する

すでに一般的な理由を排除しているので、エラーを再現する必要があります。エラーの原因となるパラメータがわかっている場合は、エラーを簡単に見つけることができます。

  • ほとんどの場合、すべてのPOST/GETパラメーターを知っていれば十分です。
  • これらだけでは再現できない場合は、追加のリクエストヘッダーを知っておく必要があります。ユーザーエージェント、accept-encoding、...など
  • それでも再現できない場合は、非常に困難になります。エラーは、状態(セッション)、現在の時刻、送信元IPアドレスなどによって異なる場合があります。

カスタムログ方式

簡単に始めましょう:すべてのパラメーターを取得するには、影響を受けるphpファイルの最初に次のように記述できます。

file_put_contents("/path/to/some/custom_error_log", date()."\n".print_r(get_defined_vars(), true), FILE_APPEND | LOCK_EX);

custom_error_logファイルはphpアプリケーションに書き込み可能でなければならないことを忘れないでください。次に、エラーログでエラーが発生した場合は、custom_error_logファイルで対応する行を見つけます。うまくいけば、リクエストを識別できるように、1秒あたりのリクエスト数はそれほど多くありません。たぶん、ソースIPのようなエラーログのいくつかの追加パラメータは、リクエストを識別するのに役立ちます(エラーログにそれが示されている場合)。そのデータから、同じPOST/GETパラメーターを使用してリクエストを再構築します。

tcpdumpメソッド

同様に非常に単純ですが、ターゲットマシンにrootアクセス権が必要な次のオプションは、tcpflowをインストールすることです。次に、フォルダを作成し、そのフォルダにcdして、(rootとして)実行しますtcpflow "port 80"。オプション(ポート80)はpcapフィルター式です。それでできることをすべて見るには、を参照してくださいman pcap-filter。これらのフィルター式でできることはたくさんあります。

これで、tcpflowはポート80ですべてのtcp接続を記録し、1つの接続に属するパッケージを組み合わせて完全なデータ交換を再構築し、このデータをファイルにダンプして、接続ごとに2つの新しいファイルを作成します。1つは着信データ用、もう1つは発信データ用です。次に、エラーログのタイムスタンプとファイルの最後に変更されたタイムスタンプに基づいて、エラーの原因となった接続のファイルを見つけます。次に、完全なhttpリクエストヘッダーを取得します。これで、同じaccept-encoding、user-agentなどの設定を含め、HTTPリクエストを完全に再構築できます。リクエストを直接netcatにパイプして、正確なリクエストを再生することもできます。ただし、sessionidのようないくつかの引数が邪魔になる可能性があることに注意してください。phpがセッションの有効期限が切れていることを検出した場合、ログインまたは予期しない何かにリダイレクトされる可能性があります。

もっと物事をあざける

これが役に立たず、マシンでエラーを再現できない場合は、モックするのが難しいすべてのものをモックすることを試みることができます。たとえば、ソースIPアドレス。これにより、いくつかのスタントが必要になる場合がありますが、それは可能です。「-w」オプションを指定したsshを使用してサーバーに接続し、トンネルインターフェイスを作成できます。次に、問題のあるIPアドレスを自分のマシンに割り当て、特定のIPにトンネルを使用するようにルート(route add host)ルールを設定します。2台のコンピューターを直接ケーブルで接続できる場合は、トンネルなしでもケーブルを接続できます。

最も重要なセッションをあざけるのを忘れないでください。print_r(get_defined_vars())を使用したメソッドを使用して、すべてのセッション変数を読み取ることができます。次に、まったく同じ変数を使用してセッションを作成する必要があります。

ユーザーに尋ねる

別のオプションは、実際にユーザーに何をしているかを尋ねることです。たぶん、あなたは彼と同じ手順をたどることができ、再現することができます。

これのどれも役に立たない場合

それが役に立たない場合...まあ...それからそれは深刻に困難になります。IPのことはすでに非常にありそうもないです。特定の地域のIPでエラーを引き起こすのはGEO-IPライブラリである可能性がありますが、これらはすべてかなりありそうもないことです。上記のいずれも問題の再現に役立たなかった場合は、custom_log_file-call/tcpflowによって生成されたすべてのデータで正しいリクエストが見つからなかった可能性があります。より正確なタイムスタンプを取得して、チャンスを増やしてください。date()の代わりにphpでmicrotime()を使用できます。エラーログで秒よりも正確な情報を取得できる場合は、Webサーバーを確認してください。より正確なタイムスタンプを提供する「tail」の独自の実装を作成します...システムの負荷を軽減して、それほど多くのデータから選択する必要がないようにします(別の時刻を試してください。

再現できたら問題を丸で囲みます

再現できたら、実際の原因を見つけるために公園を散歩する必要があります。エラーの原因となるパラメータは、試行錯誤するか、エラーの原因となった他のリクエストと比較して、類似点を探すことで見つけることができます。次に、このパラメーターの機能、アクセスするライブラリなどを確認できます。再現できなくなるまで、パラメーターを使用するすべてのコンポーネントを1つずつ無効にすることができます。次に、コンポーネントを入手して、問題をさらに深く掘り下げることができます。

見つけたものを教えてください。気になります ;-)。

于 2012-05-24T22:17:31.893 に答える
4

私もそのようなエラーがありました。何も返さないか、少なくともsqlオブジェクトを返さない代わりに、セッションクラス(session_handlerによって使用された)でsqlオブジェクトを返したことがわかりました。間違ったものを返す場合は、最初に_writeメソッドと_readメソッドを調べてください。

注意:...行0で不明-正しい行を見つける方法、それは「行0」ではありません

于 2012-05-07T16:17:33.393 に答える
3

コードをtry/catchブロックでラップする代わりに、例外ハンドラーを登録するとどうなりますか?明らかに、try / catchブロックが例外をキャッチしていないため、Apacheにエラーが記録されます。ハンドラーを登録することにより、キャッチされなかった例外が確実に処理されるようにすることができます。

また、アプリケーションで名前空間を使用している場合は、catchブロックに\ Exceptionを書き込むようにしてください(またはuseステートメントを介してExceptionクラスを含めてください)。

于 2012-05-18T10:20:24.700 に答える
3

この質問はすでに回答済みですが、誰かに役立つ可能性があるため、これを追加します。

次のような潜在的に「危険な」関数を呼び出しながら、独自のエラーハンドラーを使用して実行の制御を維持する関数から、スタックフレームなしで(意図せずに)エラーを生成することができました。

// Assume the function my_error_handler() has been defined to convert any
// PHP Errors, Warnings, or Notices into Exceptions.

function foo() {
    // maintain control if danger() crashes outright:
    set_error_handler('my_error_handler');

    try {
        // Do some stuff.

        $r = danger();
    } catch (Exception $e) {
        $r = 'Bad Stuff, Man!';
    }

    restore error_handler();
    return $r;
}

「Dosomestuff」のロジックが、restore_error_handler()の呼び出しをバイパスして、foo()から直接返された場合、 「追跡不可能な失​​敗」はプログラム実行の最後に発生します。私が経験から奪ったのはこれです:

  1. PHPは、set_error_handler()を呼び出すたびに、エラーハンドラーのスタックをより深く/より高く維持します。
  2. エラーハンドラをスタックにプッシュし、プログラムが「正常に」終了する前に自分自身の後でクリーンアップしないと、問題が発生する可能性があります。

これは特定するのが難しいバグでした-私は基本的に問題を上記の機能に絞り込み、目が出血するまでそれを見つめました。

では、私が今知っていることを知って、これをどのように追跡したでしょうか?PHPエラーハンドラの「スタック」を直接検査する方法がわからないため、シングルトンオブジェクトを使用してPHPエラーハンドラのすべての設定/復元操作をカプセル化するのが理にかなっていると思います。少なくとも、プログラムを正常に終了する前にシングルトンの状態を検査することは可能であり、「ぶら下がっている」エラーハンドラーが検出された場合、PHPが異常終了する前に適切な障害/警告メッセージを生成します。

于 2014-06-03T20:07:28.943 に答える
2

これは少し遅いかもしれませんが、サイトをローカルサーバーからリモートサーバーに移動するときに私が発見した問題の1つです。私はConcrete5cmsを使用していて、自分のサイトをローカルで開発し(xamppのWindows 8)、Cent0Sを実行しているリモートサーバーにアップロードしました。

Windows mysqlはデフォルトで大文字と小文字を区別せず、小文字のデータベースを作成します。これがリモートサーバーにアップロードされると、「0行目の不明でスタックフレームなしで例外がスローされましたか?」というメッセージが表示されました。

次に、データベーステーブルのケースを修正すると、サイトが再び機能し始めました。

于 2013-04-12T16:26:54.110 に答える
2

私たちにとって、このエラーは、SimpleXMLオブジェクトを誤ってシリアル化したことが原因でした。

5.3.3でSimpleXMLオブジェクトを使用している場合、セッションで値をシリアル化する場合は、ノード値を必要なもの(文字列など)にキャストしていることを確認してください。

  $token = $response->Token->Value;
  /* token saved in session, results in line 0 error */

$token = (string) $response->Token->Value;
  /* token saved in session, no error */
于 2014-05-27T15:53:16.997 に答える
1

まったく同じエラーが発生しました。非常に特殊なケース:名前のない関数(クロージャ)フックをオブジェクトインスタンスのフックポイントに接続する場合。その後、このオブジェクトをシリアル化しようとします。

于 2015-06-24T17:57:08.503 に答える
1

Illuminate EloquentモデルのFillableプロパティを誤って入力した後、同じエラーが発生しました。配列の最後の3つの要素に注意してください。1つにはコマがありません

protected $fillable = [
    'budget',        
    'routestatus' ,
    'userroutenumber'
    'totalmovingseconds',
    'totalidleseconds'
];
于 2019-06-27T14:29:51.563 に答える
0

同じエラーが発生しました。サーバーをcentos5からcentos6にアップグレードし、PHPを5.4から5.3にダウングレードしているようです。実際の問題はPHPapcであり、正しく構成されていませんでした。APCを確認してください。私はSymfony2を使用していたので、Symfonyでヘルプが見つかるかもしれませんプールにメモリを割り当てることができません

于 2013-05-20T13:27:55.130 に答える
0

このエラーを生成する簡単な方法の1つは、が付いた古いサーバーregister_globals = Onです。次に、2行のコードのみが必要です。

<?php
    $_SESSION["my_var"] = "string";
    $my_var = new MyClass(); //could be any class, i guess
?>

このページを一度リロードするとすぐに、Exception thrown without a stack frame in Unknown on line 0-エラーが発生します。クラスのインスタンスと(セッション)変数の間に競合があるようです。
少なくともこれは、デバッグが非常に難しいこの厄介なエラーを取得した方法です。

于 2015-04-03T08:14:08.070 に答える
0

この問題は、いくつかのSymfonyバンドルの名前空間を変更したときに発生しました。symfonyキャッシュディレクトリ内のファイルを削除すると、問題が修正されました。

于 2015-10-28T13:22:30.767 に答える
0

データベースに破損した/一貫性のないテーブルがある可能性があります。データベースをダンプしてみてください。エラーが発生した場合は、その時です。そのテーブルを修復すると、問題は解決するはずです。

クリーンインストールが機能するのはこのためです。クリーンインストールはまさにそのクリーンです。

mysqlcheckは機能するはずですが、それが表示されず、問題が発生しない場合は、上記を実行してください。

于 2017-05-29T23:43:02.940 に答える