先週末、自分のウェブサイトのウェブホストを変更しました。私が使用していたホスト サーバーは 32 ビット OS で、移動先のホスト サーバーは 64 ビットでした。予期せず、一部の PHP スクリプトで誤った結果が返されるようになりました。
私の場合、 << および >> (ビットシフト) 操作が原因でした。結果を 0xFFFFFFFF でマスクする必要があり、結果が負の場合は以前と同じように機能するように変更しました。
私の PHP スクリプトには、探すべき問題が他にありませんか?
先週末、自分のウェブサイトのウェブホストを変更しました。私が使用していたホスト サーバーは 32 ビット OS で、移動先のホスト サーバーは 64 ビットでした。予期せず、一部の PHP スクリプトで誤った結果が返されるようになりました。
私の場合、 << および >> (ビットシフト) 操作が原因でした。結果を 0xFFFFFFFF でマスクする必要があり、結果が負の場合は以前と同じように機能するように変更しました。
私の PHP スクリプトには、探すべき問題が他にありませんか?
これは高水準言語であるため、ビットに関係のないもの (ビット演算子、ビットシフト) はすべて同じです。
整数は32ビットではなく64ビットにすることができます。これが問題を引き起こす可能性があるいくつかの奇妙なケースがあります。
strtotimeは、64ビットでは動作が異なります。PHP.netから:
ノート:
タイムスタンプの有効な範囲は、通常、1901年12月13日金曜日20:45:54UTCから2038年1月19日火曜日03:14:07UTCまでです。(これらは、32ビット符号付き整数の最小値と最大値に対応する日付です。)さらに、すべてのプラットフォームが負のタイムスタンプをサポートしているわけではないため、日付範囲はUnixエポックより前に制限される場合があります。これは、たとえば1970年1月1日より前の日付は、Windows、一部のLinuxディストリビューション、およびその他のいくつかのオペレーティングシステムでは機能しないことを意味します。ただし、PHP 5.1.0以降のバージョンでは、この制限が克服されています。
PHPの64ビットバージョンの場合、タイムスタンプの有効範囲は事実上無限です。64ビットはどちらの方向でも約2930億年を表すことができるからです。
strtotime( '0000-00-00')を実行しているコードがあり、結果がfalseになると予想しました。64ビットに移動すると、負の整数が返されました。
ビット操作には、システム/アーキテクチャ間で移植可能にするために特別な注意が必要です。
C では、符号なし変数を使用して << および >> 操作を移植可能にすることができます。これにより、負の数に対する 1/2 の補数規則が削除されます。
原則として、ビット操作 (& や | など) に固定長マスクを使用しないでください。これらはアーキテクチャに依存します。
例えば。最後の 4 ビットのリセット: マスク 0xF0 は 8 ビット アーキテクチャでは機能しますが、16 ビットでは機能しません。結果は異なります (16 ビットには、マスクに含まれない他のビットが設定されている場合があります)。
この問題を解決するには、~ 演算子を使用します。マスク ~0xF は 0xF0 と同等ですが、どのアーキテクチャでも機能します。最後の 4 ビットを除くすべてのビットがリセットされます
表示される問題は、データの32ビットバイナリ表現に依存している場合のみです。主にPHPは符号付き整数を使用するため、ハッシュやキー生成などの問題が発生します。(int)を使用してintに明示的にキャストすると、2 ^ 32を超える数値はラップされますが、64ビット環境ではラップされません。もちろん>2^64でない限り。
4ビットと8ビットの例:
10進値の問題:
0010 >> 1 = 0001 [ 1 dec ]
0000 0010 >> 1 = 0000 0001 [ 1 dec ]
これらは両方とも同じ結果を生成します(10進数で)。ただし、次のようになります。
0100 << 1 = 1000 [ -8 dec ]
0000 0100 << 1 = 0000 1000 [ 16 dec ]
ラッピングの問題:
1000 << 1 = 0000 [ 0 dec ]
0000 1000 << 1 = 0001 0000 [ 32 dec ]
すべての整数/浮動小数点演算は64ビット値として扱われるため、最終結果が32ビットチャンクに依存している場合は、そのような値を補正する必要があります。
浮動小数点除算の結果は、64 ビットへの増加の影響を受けます。したがって、浮動小数点除算の結果をハードコードされた定数と比較するなどの愚かなことをするコードがある場合は、それが壊れることを期待してください。