JPCERT コーディネーションセンター

DCL17-C. volatile 修飾された変数が間違ってコンパイルされることに注意

ルール「DCL34-C. キャッシュできないデータには volatile を使う」で詳しく説明しているように、volatile修飾された変数は「抽象計算機の規則に厳密に従って評価しなければならない」[ISO/IEC 9899:2011]。言葉をかえると、volatile 修飾子を使うことで、コンパイラに対して変数をキャッシュする最適化をしないように指示することができる。

しかし、"Volatiles are miscompiled, and what to do about it" [Eide and Regehr] が示したように、彼らがテストしたコンパイラのすべてが、volatile アクセスという点に関して何パーセントかの間違ったコードを生成した。それゆえ、言語規格に従ったvolatile動作が必要な場合に、自分のコンパイラがどのように動作するか知っておく必要がある。この 2 人の著者は、この手のエラーを解決するワークアラウンドの提供も行っている。

違反コード

Eide および Regeher の論文で示されているように、以下のコードは、IA32 向け GCC 4.3.0 で最適化フラグ -Os を立ててコンパイルすると間違ったコードを生成する。

const volatile int x;
volatile int y;
void foo(void) {
  for(y = 0; y < 10; y++) {
    int z = x;
  }
}

変数 xvolatile 修飾されているので、このプログラム中で 10 回アクセスされるべきである。しかし、コンパイルされたあとのオブジェクトコードを見てもわかるように、ループの巻き上げ最適化により x は一度しかアクセスされない。

foo:
  movl $0, y
  movl x, %eax
  jmp .L2
.L3:
  movl y, %eax
  incl %eax
  movl %eax, y
.L2:
  movl y, %eax
  cmpl $10, %eax
  jg .L3
  ret

x がハードウェアレジスタやその他メモリマップされたデバイスなどアクセス時に副作用を持つものを表す場合、上記の誤ってコンパイルされたコード例は予期せぬ動作を引き起こすかもしれない。

適合コード

Eide と Regehr はワークアラウンドとして、volatile へのアクセスを関数呼出しで包む方法をテストした。この手法について、彼らはこう説明している:「コンパイラが間違ったコードを出すアクションを、関数呼出しという異なるアクションに置き換えることで、コンパイラが正しいコードを出すようにできる」[Eide and Regehr]たとえば、上記のレコメンデーションに違反したコードのワークアラウンドとして、以下の例が考えられる。

int vol_read_int(volatile int *vp) {
  return *vp;
}
volatile int *vol_id_int(volatile int *vp) {
  return vp;
}

const volatile int x;
volatile int y;
void foo(void) {
  for(*vol_id_int(&y) = 0; vol_read_int(&y) < 10; *vol_id_int(&y) = vol_read_int(&y) + 1) {
    int z = vol_read_int(&x);
  }
}

Eide および Regehr が提案するワークアラウンドは、テストしたコンパイラに存在する多くの volatile アクセスに関するバグに効果を発揮する。しかし、コンパイラは常に進化し続けているため、クリティカルなコードについては、実配備を想定してコンパイルし、その結果のオブジェクトコードが正しいふるまいをするかどうかを確認すべきである。

リスク評価

ミッションクリティカルな状況では volatile 修飾子は注意して使うべきである。volatile 修飾子を使ってあるふるまいを想定しているコードについては、コンパイラのバグがないかどうか、常にオブジェクトコードレベルで検査すること。

ルール

深刻度

可能性

修正コスト

優先度

レベル

DCL17-C

P4

L3

参考資料
[Eide and Regehr] "Volatiles are miscompiled, and what to do about it"
[ISO/IEC 9899:2011] Section 6.7.3, "Type Qualifiers"
翻訳元

これは以下のページを翻訳したものです。

DCL17-C. Beware of miscompiled volatile-qualified variables (revision 22)

Top へ

Topへ
最新情報(RSSメーリングリストTwitter