名前空間
変種
操作

解析可能性

提供: cppreference.com
< c‎ | language

C 言語のこのオプショナルな拡張は未定義動作の一部の形式を実行した潜在的な結果を制限します。 これはそのようなプログラムの静的解析の効率を向上させます。 解析可能性は定義済みマクロ定数 __STDC_ANALYZABLE__(C11) がコンパイラによって定義されている場合にのみ有効であることが保証されます。

コンパイラが解析可能性をサポートする場合、動作が未定義な言語またはライブラリのあらゆる要素は、さらに致命的有界に分類され、すべての有界な未定義動作の動作は以下で規定するように制限されます。

目次

[編集] 致命的な未定義動作

致命的な未定義動作は任意のオブジェクトの境界外のメモリ書き込みまたは volatile メモリ読み込みを行う可能性を持ちます。 致命的な未定義動作を持つプログラムはセキュリティ上の懸念があります。

以下の未定義動作のみが致命的です。

  • 生存期間外のオブジェクトへのアクセス (ダングリングポインタの使用など)
  • 宣言が完全でないオブジェクトへの書き込み
  • 指す先の関数の型と互換でない型の関数ポインタを通した関数呼び出し
  • オブジェクトを指示しない左辺値式が評価された
  • 文字列リテラルの変更が試みられた
  • 無効なポインタ (ヌルや不定) または最後の要素の次を指すポインタの逆参照
  • 非 const ポインタを通した const オブジェクトの変更
  • 無効な引数を用いた標準ライブラリ関数またはマクロの呼び出し
  • 期待と異なる型の引数を用いた可変長の標準ライブラリ関数の呼び出し (変換指定子とマッチしない型の引数を用いた printf の呼び出しなど)
  • 呼び出し履歴上に setjmp がない、スレッドを横切る、または VM 型のスコープ内からの longjmp
  • free または realloc で解放されたポインタのあらゆる使用
  • 文字列またはワイド文字列のライブラリ関数に配列の境界外をアクセスさせる

[編集] 有界な未定義動作

有界な未定義動作は不正なメモリ書き込みを行うことはできませんが、トラップを発生させたり不定値を生成または格納する可能性があります。

  • 致命的のリストに掲載されていないすべての未定義動作は有界です。 例えば、
  • マルチスレッドのデータ競合
  • 自動記憶域期間を持つ不定値の使用
  • 厳密なエイリアシングの違反
  • アラインされていないオブジェクトのアクセス
  • 符号付き整数のオーバーフロー
  • 配列されない副作用が同じスカラーを変更するまたは同じスカラーを変更し読み込む
  • 浮動小数点から整数またはポインタから整数への変換のオーバーフロー
  • 負のビット数または大きすぎるビット数による左ビットシフト
  • ゼロによる整数除算
  • void 式の使用
  • 正確でなくオーバーラップしたオブジェクトの直接代入または memcpy
  • restrict の違反
  • などなど... 致命的のリストに掲載されていないすべての未定義動作

[編集] ノート

有界な未定義動作は一部の最適化を無効化します。 解析可能性を有効化したコンパイルは、そうでなければ未定義動作に違反した可能性のあるソースコードの因果関係を維持します。

解析可能性拡張は、処理系定義の動作のひとつの形式として、トラップが発生するときに実行時制約ハンドラを呼んでも構いません。

[編集] 参考文献

  • C11 standard (ISO/IEC 9899:2011):
  • 6.10.8.3/1 Conditional feature macros (p: 177)
  • Annex L Analyzability (p: 652-653)