未定義動作(UB、undefined behavior)とは、コード内の動作が標準化されていない場合のことです。この場合、コンパイラは任意の決定を下すことができ、プログラムは異なるプラットフォームやコンパイラで異なる結果を出す場合もありますし、正式には核戦争を引き起こすことさえあります!UBの使用はC++における最も危険なエラーです。
UBの例:
int* p = new int[2]; delete[] p; int x = p[1]; // UB: 解放後のメモリへのアクセス
UBを防ぐために:
次のコードで何が起こりますか?
int a = 42; int b = a++ + ++a;
bの値は何になりますか?
回答:
このコードはUBを引き起こします。なぜなら、操作の間に順序点(sequence points)が無い状態で変数aを変更し、読んでいるからです。標準は特定の結果を保証せず、コンパイラは任意の結果を取得したり、予期しないコードを生成したりすることがあります。
物語 データストレージシステムのプロジェクトで、ある開発者が低レベルの関数で配列の境界を越えるアクセスを行いました。UBは特定のユーザーデータでのみ発生し、ファイル構造の破損やクライアントデータの損失を引き起こしました。
物語 マイクロコントローラ用のプロジェクトでは、初期化されていない変数の読み取りを伴う構造が見つかりました。テストは通過しましたが、デバイスのリリースから1年後にUBによるランダムなエラーが発覚しました:変数が時々ゴミ値を含んでいました。
物語 大規模なオープンソースプロジェクトで、異なるコードの部分から二重に解放されたディスクリプタが発見されました。最初は非常にまれにUBが現れましたが、新しいOSバージョンでは頻繁なクラッシュにつながるようになりました。