メインコンテンツ

誤って失敗する可能性のある関数はループでラップされません

誤りの可能性がある失敗後のループによる失敗条件のチェック

説明

この欠陥は、誤って失敗とされる可能性のある以下のアトミックな比較関数と交換関数が、ループの外側から呼び出された場合に発生します。

  • C のアトミック関数:

    • atomic_compare_exchange_weak()

    • atomic_compare_exchange_weak_explicit()

  • C++ のアトミック関数:

    • std::atomic<T>::compare_exchange_weak(T* expected, T desired)

    • std::atomic<T>::compare_exchange_weak_explicit(T* expected, T desired, std::memory_order succ, std::memory_order fail)

    • std::atomic_compare_exchange_weak(std::atomic<T>* obj, T* expected, T desired)

    • std::atomic_compare_exchange_weak_explicit(volatile std::atomic<T>* obj, T* expected, T desired, std::memory_order succ, std::memory_order fail)

これらの関数は、obj および expected の参照先のオブジェクト表現のメモリ内容を比較します。比較では、メモリ内容が等しい場合でも、誤って false が返される場合があります。この誤った失敗により、一部のプラットフォームでは関数が高速になります。

リスク

誤って失敗とされるアトミックな比較および交換関数は、予期しない結果や予期しない制御フローを引き起こす可能性があります。

修正方法

誤って失敗とされる可能性のあるアトミックな比較および交換関数をループ内にラップします。誤りの可能性がある失敗後に、ループで失敗条件をチェックします。

すべて展開する

#include <stdatomic.h>

extern void reset_count(void);
atomic_int count = ATOMIC_VAR_INIT(0);

void increment_count(void)
{
    int old_count = atomic_load(&count);
    int new_count;
    new_count = old_count + 1;
    if (!atomic_compare_exchange_weak(&count, &old_count, new_count))
        reset_count();

}

この例では、increment_count()atomic_compare_exchange_weak() を使用して countold_count を比較します。カウントが等しい場合、countnew_count にインクリメントされます。カウントが等しくない場合、カウントはリセットされます。atomic_compare_exchange_weak() が誤って失敗とされると、カウントは不必要にリセットされます。

修正 — atomic_compare_exchange_weak()while ループ内にラップ

1 つの修正方法として、atomic_compare_exchange_weak() の呼び出しを while ループ内にラップします。誤りの可能性がある失敗後に、ループで失敗条件をチェックします。

#include <stdatomic.h>

extern void reset_count(void);
atomic_int count = ATOMIC_VAR_INIT(0);

void increment_count(void)
{
    int old_count = atomic_load(&count);
    int new_count;
    new_count = old_count + 1;

    do {
        reset_count();

    } while (!atomic_compare_exchange_weak(&count, &old_count, new_count));

}

結果情報

グループ: 同時実行
言語: C | C++
既定値: オフ
コマンド ライン構文: SPURIOUS_FAILURE_NOT_WRAPPED_IN_LOOP
影響度: Low

バージョン履歴

R2018b で導入