Диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.
Это правило актуально только для языка C.
Прямой доступ (оператор . или ->) к полям структур или объединений объектов атомарных типов может привести к гонке данных. Вместо этого доступ к объекту следует осуществлять с использованием специальных функций из <stdatomic.h> и оператора присваивания =.
Стандарт C определяет следующие функции для доступа к атомарным объектам:
atomic_initatomic_storeatomic_loadatomic_exchangeatomic_compare_exchangeСтандарт гарантирует, что выполнение атомарных операций с данными, которые используются в нескольких потоках, не приведёт к гонке данных. Однако прямой доступ к полям объектов атомарных типов нарушает эту гарантию.
Примечание. Функция atomic_init сама по себе не предотвращает потенциально возможную гонку данных. Если несколько потоков в момент инициализации обращаются к переменной, даже используя атомарные операции, это всё равно может привести к состоянию гонки.
Пример некорректного кода:
typedef struct {
int32_t width;
int32_t height;
} rectangle_t;
_Atomic rectangle_t rect;
int foo(void)
{
rect.width = 300;
return 0;
}
В примере прямая запись rect.width = 300; может привести к гонкам данных и невалидному состоянию объекта.
Руководство MISRA предлагает исправлять подобный код следующим образом:
typedef struct {
int32_t width;
int32_t height;
} rectangle_t;
_Atomic rectangle_t rect;
int foo(void)
{
rectangle_t tmp;
tmp = atomic_load(&rect);
tmp.height = 400;
atomic_store(&rect, tmp);
return 0;
}
Однако такое исправление нельзя считать самодостаточным. Исчезла проблема неатомарного изменения полей в структуре, но добавилась новая потенциальная проблема синхронизации.
Рассмотрим следующий сценарий:
foo и скопировал структуру в переменную tmp.tmp.height, второй поток может поменять значение rect.width.atomic_store, перезаписывает rect.width старым значением. Ошибка.Чтобы избежать такой проблемы, может потребоваться дополнительная синхронизация между разными потоками. Однако данная тема выходит за рамки диагностического правила MISRA.
Данная диагностика классифицируется как:
|