解析可能性 (Analyzability)
From cppreference.com
これはC言語のオプションの拡張機能であり、一部の未定義動作を実行した際の結果を限定することで、そのようなプログラムの静的解析の有効性を向上させます。解析可能性は、定義済みマクロ定数 __STDC_ANALYZABLE__(C11) がコンパイラによって定義されている場合にのみ有効であることが保証されます。
コンパイラが解析可能性をサポートしている場合、動作が未定義であるすべての言語構文またはライブラリ構文は、さらに致命的 (critical) な未定義動作と有界 (bounded) な未定義動作に分類され、すべての有界な未定義動作 (UB) の振る舞いは以下で指定されるように制限されます。
目次 |
[編集] 致命的な未定義動作
致命的なUB (Critical UB) とは、どのオブジェクトの範囲外でもメモリ書き込みやvolatileなメモリ読み取りを実行する可能性のある未定義動作です。致命的な未定義動作を持つプログラムは、セキュリティ上の脆弱性を持つ可能性があります。
以下の未定義動作のみが致命的とされます
- その生存期間を外れたオブジェクトへのアクセス (例: ダングリングポインタを介したアクセス)
- 宣言に互換性のないオブジェクトへの書き込み
- 指し示す関数の型と互換性のない型の関数ポインタを介した関数呼び出し
- 左辺値式 (lvalue expression) が評価されたが、オブジェクトを指していない
- 文字列リテラルの変更の試み
- 無効な (null、不定など) ポインタやpast-the-end (配列の末尾の次) ポインタのデリファレンス
- 非constポインタを介したconstオブジェクトの変更
- 標準ライブラリ関数またはマクロを無効な引数で呼び出す
- 可変長引数をとる標準ライブラリ関数を予期しない型の引数で呼び出す (例: 変換指定子と一致しない型の引数でprintfを呼び出す)
- 呼び出しスコープの上位にsetjmpがない、スレッドをまたぐ、またはVM型のスコープ内からのlongjmpの呼び出し
- freeまたはreallocによって解放されたポインタのあらゆる使用
- 文字列またはワイド文字列ライブラリ関数が配列の範囲外にアクセスする
[編集] 有界な未定義動作
有界なUB (Bounded UB) とは、不正なメモリ書き込みを実行することはない未定義動作ですが、トラップしたり、不定値を生成または格納したりする可能性があります。
- 致命的として挙げられていないすべての未定義動作は有界であり、以下を含みます
- マルチスレッドのデータ競合
- 自動記憶域期間を持つ不定値の使用
- 厳密なエイリアシング違反
- アライメントされていないオブジェクトへのアクセス
- 符号付き整数のオーバーフロー
- 順序付けられていない副作用が同じスカラを変更する、または同じスカラを変更かつ読み取る
- 浮動小数点数から整数へ、またはポインタから整数への変換におけるオーバーフロー
- 負の数または大きすぎるビット数によるビットシフト
- ゼロによる整数除算
- void式の使用
- 不正確にオーバーラップしたオブジェクトへの直接の代入またはmemcpy
- restrict違反
- など... 致命的なリストにないすべての未定義動作。
[編集] 注意
有界な未定義動作は、特定の最適化を無効にします。解析可能性を有効にしてコンパイルすると、ソースコードの因果関係が保持されますが、そうでなければ未定義動作によって因果関係が破られる可能性があります。
解析可能性拡張は、処理系定義の動作の一形態として、トラップが発生したときに実行時制約ハンドラが呼び出されることを許可します。
[編集] 参照
- C11標準 (ISO/IEC 9899:2011)
- 6.10.8.3/1 Conditional feature macros (p: 177)
- Annex L Analyzability (p: 652-653)