以下の例を見てください:
コードをコピーします コードは次のとおりです:
$array = array(1,2,3);
function add (&$arr) {
$arr[] = 4;
add(@$array);
/**
この時点では、$array は変更されておらず、出力:
Array
(
[0] => 1
[1] => 2
[2] => 3
)
*/
print_r($array); **
エラー抑制なしの場合、出力は通常です:
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
*/
?>
私はこれまでこの問題に遭遇したことがなかったので、既製の答えがあるかどうかを確認するためにまず関連情報を探しましたが、誰かが答えていることがわかりました。同様の問題を PHP Bug: http://bugs.php.net/bug.php?id=47623 に報告しましたが、PHP 公式はまだ解決しておらず、返答もありません
gdb による追跡後、関数の前のパラメーター opcode が間違っていることが判明しました。呼び出しが異なります:
コードをコピーします
コードは次のとおりです: //No エラー抑制機能を使用する場合 OPCODE = SEND_REF
//エラー抑制機能を使用した後OPCODE = SEND_VAR_NO_RE
問題は最初に特定されましたが、この違いの理由は何でしょうか?
OPCODE が異なるため、異なる分岐をとったのはこのレベルであると考えると、問題は簡単に特定できます。
PHP の構文解析の段階では、「@」 + expr の形式のエントリは expr_without_variable に変換されることがわかります。この種のノードの意味は、変数値、つまりリテラル値が存在しないことです。リテラル値は (変数ではないため) 参照を渡すことができないことは誰もが知っているので、この違いが生じます。
// ... 省略されています | '@' {zend_begin_silence (& $ 1 TSRMLS_CC);} expr { lence (& $1 TSRMLS_CC) } //ここで ZEND_SEND_VAL 分岐が選択されますnon_empty_function_call_parameter_list:
expr_without_variable { ....} //この分岐は誤って選択されます variable {..... } //正常 状況
の結果、コンパイル中に異なる OPCODE が生成されました
最後に、PHP のこのバグのページで理由を説明しました。興味がある場合は、私の英語力を確認してください。最後に、この興味深い内容を提供してくれた cici netizen に感謝します。質問です
以上、PHPエラーサプレッサー@の参照パラメータ転送失敗の原因となるバグの解析を内容も含めて紹介しましたので、PHPチュートリアルに興味のある方の参考になれば幸いです。