メインコンテンツ

式の中でアトミック変数へのアクセスが 2 回行われています

変数をアクセスの間に変更可能

説明

この欠陥は、C のアトミック型または C++ の std::atomic クラスの変数が 1 つの式の中で 2 回登場する場合に発生します。これには次のようなものがあります。

  • 変数に対する 2 回のアトミックな読み取り操作。

  • 変数に対するアトミックな読み取り操作と別個のアトミックな書き込み操作。

C 標準では、スレッドセーフになっていて、データ レース状態を引き起こさない、アトミック変数に対する特定の操作が定義されています。個別の操作とは異なり、1 つの式における同じアトミック変数に対する 1 組の操作はスレッドセーフではありません。

リスク

スレッドは、1 組のアトミック操作の間にアトミック変数を変更することができ、その結果、データ レース状態になる可能性があります。

修正方法

同じ式の中でアトミック変数を 2 回参照しないようにします。

すべて展開する


#include <stdatomic.h>

atomic_int n = ATOMIC_VAR_INIT(0);

int compute_sum(void)
{
    return n * (n + 1) / 2;
}

この例では、グローバル変数 ncompute_sum() の return ステートメント内で 2 回参照されています。n の値は、2 つの別個の読み取り操作の間に変わる可能性があります。compute_sum() は誤った値を返すおそれがあります。

修正 — 変数を関数の引数として渡す

1 つの修正方法として、変数を関数の引数 n として渡します。変数はメモリにコピーされ、そのコピーに対する読み取り操作により compute_sum() で正しい結果が返されることが保証されます。atomic_int 型の代わりに int 型の変数を渡す場合でも、この修正は有効です。


#include <stdatomic.h>

int compute_sum(atomic_int n)
{
    return n * (n + 1) / 2;
}

結果情報

グループ: 同時実行
言語: C | C++
既定値: 手書きコードはオン、生成コードはオフ
コマンド ライン構文: ATOMIC_VAR_ACCESS_TWICE
影響度: Medium

バージョン履歴

R2018b で導入