EXP32-C. 非 volatile 参照により volatile オブジェクトにアクセスしない
volatile 修飾型オブジェクトは、処理系が関与しない方法で変更されたり、その他の未知の副作用を持つ可能性がある。非 volatile 値を使用して volatile オブジェクトを参照することができるが、未定義の動作が引き起こされる可能性がある。C 標準 [ISO/IEC 9899:2011] セクション 6.7.3 には次のように記載されている。
volatile 修飾型で定義されたオブジェクトを、非 volatile 修飾型の左辺値を使って参照しようとした場合、その動作は未定義とする。
(C 標準の附属書 J 「未定義の動作」の 65 も参照すること。)
違反コード
この例では、volatile オブジェクトは非 volatile 修飾の参照を通じてアクセスされ、未定義の動作が発生する。
static volatile int **ipp;
static int *ip;
static volatile int i = 0;
printf("i = %d.\n", i);
ipp = &ip; /* 最新のコンパイラでは警告を出す */
ipp = (int**) &ip; /* 制約違反、警告も出す */
*ipp = &i; /* 問題なし */
if (*ip != 0) { /* 問題なし */
  /* ... */
}
代入 ipp = &ip は安全ではない。なぜなら、非 volatile 修飾の参照 ip を通じて、それに続く有効なコードが volatile オブジェクト i の値を参照できるからである。この例では、i が volatile でなければ i != 0 は必ず偽になるため、コンパイラは最適化により if ブロック全体を除去する可能性がある。
処理系固有の詳細
Microsoft Visual C++ .NET(2003) および MS Visual Studio 2005 では、この例は警告なしでコンパイルされる。
MS Visual Studio 2008 では、この例はコンパイルできない。エラーメッセージは次のとおり。
error C2440: '=' : cannot convert from 'int **' to 'volatile int **'
GCC のバージョン 3.2.2 および 4.1.3 は警告を出すが、コンパイルは行われる。
適合コード
以下のコード例では、ip を volatile として宣言している。
static volatile int **ipp;
static volatile int *ip;
static volatile int i = 0;
printf("i = %d.\n", i);
ipp = &ip;
*ipp = &i;
if (*ip != 0) {
  /* ... */
}
リスク評価
キャストにより volatile を無効にすると、非 volatile の参照を通じたアクセスが行われる可能性がある。これにより未定義またはおそらく意図せぬプログラムの動作が引き起こされる可能性がある。
| ルール | 深刻度 | 可能性 | 修正コスト | 優先度 | レベル | 
|---|---|---|---|---|---|
| EXP32-C | 低 | 高 | 中 | P6 | L2 | 
自動検出(最新の情報はこちら)
| ツール | バージョン | チェッカー | 説明 | 
|---|---|---|---|
| Compass/ROSE | 
 | 
 | 
 | 
| GCC | V. 4.3.5 | 
 | GCC は  | 
| LDRA tool suite | V. 8.5.4 | 344 S | 実装済み | 
| PRQA QA-C | 8.1 | 0312 | 実装済み | 
関連するガイドライン
| CERT C++ Secure Coding Standard | EXP32-CPP. Do not access a volatile object through a non-volatile reference | 
| ISO/IEC TR 24772:2013 | Pointer Casting and Pointer Type Changes [HFC] Type System [IHN] | 
| MISRA-C | Rule 11.5 | 
参考資料
| [ISO/IEC 9899:2011] | Section 6.7.3, "Type Qualifiers" | 
翻訳元
これは以下のページを翻訳したものです。
EXP32-C. Do not access a volatile object through a non-volatile reference (revision 75)

 
 コメント
コメント 共  有
共  有
