exponenta event banner

Функция, которая может ошибочно завершиться сбоем, не заключенная в цикл

Контур проверяет состояние отказа после возможного ложного отказа

Описание

Этот дефект возникает, когда следующие функции атомарного сравнения и обмена, которые могут ошибочно завершиться сбоем, вызываются извне цикла.

  • Атомные функции 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() выдерживать сравнение count и old_count. Если счетчики равны, count увеличивается до new_count. Если они не равны, счетчик сбрасывается. Когда atomic_compare_exchange_weak() ошибочно, счетчик сбрасывается без необходимости.

Коррекция - перенос atomic_compare_exchange_weak() в while Петля

Одной из возможных корректировок является перенос вызова в 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
Воздействие: Низкий
Представлен в R2018b