no-image

PHP5.3.14以降のarray_walkで内部ポインタが破壊される

たぶんこれ bug だと思うので、PHPに詳しい人達に調べてもらいたい所ですが、最近のPHP5.3系と5.4系で array_walk() を使うと、その戻り値となる配列の内部ポインタ(internal array pointer)が壊れてしまうようです。

以下のコードは、配列に対して array_walk() を実行したあと、 current() でその配列のポインタを参照しています。このコードは、PHPのバージョンによって動作が変わります。

具体的には、PHP5.3.13で実行するとoが表示され、PHP5.4.17で実行するとxが表示されます。

いつの時点から挙動が変わっているのか知りたくなったので、PHP Sandbox, test PHP online, PHP tester を使って、各バージョン毎の差位を調べて表にしてみました。

version result
5.4.17 x
5.4.13 x
5.4.12 x
5.4.11 x
5.4.10 x
5.4.9 x
5.4.8 x
5.4.7 x
5.4.6 x
5.4.5 x
5.4.4 x
5.4.3 o
5.4.2 o
5.4.1 o
5.4.0 o
5.3.23 x
5.3.22 x
5.3.21 x
5.3.20 x
5.3.19 x
5.3.18 x
5.3.17 x
5.3.16 x
5.3.15 x
5.3.14 x
5.3.13 o
5.3.12 o
5.3.11 o
5.3.10 o
5.3.3 o
5.3.2 o
5.3.1 o
5.3.0 o
5.2.17 o
5.2.16 o
5.1.6 o
5.1.5 o
5.0.5 o
5.0.4 o
4.4.9 o

PHP5.4.3と、PHP5.3.13を最後に、挙動が変わってしまっているようです。

この挙動の変化を回避するには、 array_walk() の後に、 reset() を呼んで、明示的に内部ポインタを初期化してあげる事が必要です。

array_walk() のマニュアルには、「array_walk() is not affected by the internal array pointer of array.」 とあるので、 reset() しなくても良いのが正しい挙動だと思うのですが…