メインコンテンツ

CERT C++: CON41-C

Wrap functions that can fail spuriously in a loop

説明

ルール定義

誤って失敗する可能性のある関数はループ内にラップします。1

Polyspace 実装

ルール チェッカーは、"誤って失敗する可能性のある関数はループでラップされません" をチェックします。

すべて展開する

問題

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

  • 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 が返される場合があります。この誤った失敗により、一部のプラットフォームでは関数が高速になります。

リスク

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

修正方法

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

例 — ループ内にラップされていない atomic_compare_exchange_weak()
#include <atomic>
#include <stdbool.h>
using namespace std;
static atomic<bool> flag(false);
void toggle_flag(void)
{
	bool old_flag = atomic_load(&flag);
	bool new_flag;
	if (!atomic_compare_exchange_weak(&flag, &old_flag, new_flag)){//Noncompliant
		new_flag = !old_flag;
	}

}

bool get_flag(void)
{
	return atomic_load(&flag);
}

この例では、関数 toggle_flagatomic_compare_exchange_weak() を使用して flagold_flag を比較します。変数が等しい場合は、flagnew_flag に切り替えられます。atomic_compare_exchange_weak() が誤って失敗とされると、フラグが不必要に切り替えられます。

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

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

#include <atomic>
#include <stdbool.h>
using namespace std;
static atomic<bool> flag(false);


void toggle_flag(void)
{
  bool old_flag = atomic_load(&flag);
  bool new_flag;
  do {
    new_flag = !old_flag;
  } while (!atomic_compare_exchange_weak(&flag, &old_flag, new_flag));

}

bool get_flag(void)
{
    return atomic_load(&flag);
}

チェック情報

グループ: 10.同時実行 (CON)

バージョン履歴

R2019a で導入


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.