グリフォン Advent Calendar 2018 10日目の記事を担当しました、森と申します。
運用プロジェクトでサーバーサイドエンジニアをしています。
この記事では運用中に出会ったPHPで驚いたバグについて書きます。
※この記事はGRIPHONE Advent Calendar 2018 10日目の記事です。
https://adventar.org/calendars/3147
https://qiita.com/advent-calendar/2018/griphone
バグのエラー内容
大型の改修が入ったあとにデバッグをしてもらったところ、以下のようなエラーログが出ました。
Function name must be a string
実際のコードはお見せできないのですが、例えば以下のようなコードで再現することができます。
function calc_sum($a, $b){
return $a + $b;
}
$first_arg = 100;
$second_arg = 200;
echo sprintf(
'result = %d',
calc_sum(
$first_arg
(@$second_arg ?: NULL)
)
);
このコードを実行すると以下のエラーが出ます。
Fatal error: Uncaught Error: Function name must be a string
自分が調査した時はおかしな関数呼び出しがないように見えるのでなんでこんなエラーになるのか不思議でした。
PHPerの方はぜひどこがおかしいのか探してみてください!
バグの原因
さて、おかしい箇所はわかりましたか?
正解は以下です。よく見るとcalc_sum
関数の第一引数$first_arg
にカンマがついていませんね。
// 間違い
$first_arg
// 正解
$first_arg,
さて、これでなぜFunction name must be a string
エラーが出てしまうのかというと、以下の部分が関数呼び出しの構文として解釈されてしまったためです。
$first_arg
(@$second_arg ?: NULL)
$first_arg
が関数名、(@$second_arg ?: NULL)
が引数として解釈されたのに、$first_arg
が100と関数名としてふさわしくなかったため、このようなエラーが出た、ということになります。
この例はプログラムも短く、ロジックも簡単なので原因がわかりやすいと思いますが、実際のプログラムは10000行を超えるファイル、ロジックもかなり複雑だったので原因判明までに1時間強かかりました。こういう構文が変わってしまうようなタイポはシンタックスエラーで落ちるだろう、という先入観があったのも良くなかったと思います。
全く心当たりのないエラーに遭遇した時、PHPでは構文が意図したものにならずにバグが起きることもあるということを覚えておくと役に立つと思います。