こんにちは。新規事業推進室の石田です。
先週、店舗maticの新バージョンを本番環境へリリースしました。
どんなに準備しても本番に適用すると思ってもやっぱり本番環境ではなにか問題が発生するわけで・・・
今日は、本番環境への適用後に発覚してパッチリリースを余儀なくされたバグについてお話します。
バグの原因は、Javaのインクリメント演算子(++)を変数への代入式の中でつけていたときの評価順というもので、原因究明にはかなり手こずりました。
以下は、i = 1 の状態で、以下の各言語でインクリメント演算子つきの変数同士の演算を試してみた結果です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
Java (Sun JVM 1.6.0_17) ++i = 2 i++ = 1 ++i + ++i = 5 i++ + i++ = 3 ++i + i++ = 4 i++ + ++i = 4 ++i + i++ + ++i = 8 i++ + ++i + i++ = 7 C (gcc 4.1.0 (i586)) ++i = 2 i++ = 1 ++i + ++i = 6 i++ + i++ = 2 ++i + i++ = 4 i++ + ++i = 4 ++i + i++ + ++i = 7 i++ + ++i + i++ = 6 Perl 5.8.8 ++i = 2 i++ = 1 ++i + ++i = 6 i++ + i++ = 3 ++i + i++ = 5 i++ + ++i = 4 ++i + i++ + ++i = 9 i++ + ++i + i++ = 7 JavaScript (IE6/IE7/IE8/Firefox3.6) ++i = 2 i++ = 1 ++i + ++i = 5 i++ + i++ = 3 ++i + i++ = 4 i++ + ++i = 4 ++i + i++ + ++i = 8 i++ + ++i + i++ = 7 Ruby 1.8.3 (parse error で計算不能) |
なんと、言語によって結果がバラバラ。
JavaとJavaScriptが一番自然ですかね。
Perlなんてどこをどういう順序で評価したらそうなるのか意味不明です。
さらに、今回のバグなんですが、式の計算結果がJVMによるHotSpotの最適化の前後で変わってしまっているような状況です。
不具合の内容もさすがにテストで見逃すようなものではなかったし・・・同じバイナリが検証環境では正しく動いていたし・・・と訳分りません。
まあ、副作用のあるインクリメント/デクリメント演算子を式の中で使うなという事以外対策の取りようがなさそうです。
皆様もお気をつけください。
では。