# V2647. MISRA. Structure and union members of atomic objects should not be directly accessed.

This diagnostic rule is based on the MISRA (Motor Industry Software Reliability Association) software development guidelines.

This diagnostic rule is relevant only for C.

Direct access (the `.` or `->` operator) to structure data members or unions of atomic type objects can result in a data race. Instead, access the object using the special functions from `<stdatomic.h>` and the `=` assignment operator.

The C standard defines the following functions for accessing atomic objects:

- `atomic_init`
- `atomic_store`
- `atomic_load`
- `atomic_exchange`
- `atomic_compare_exchange`

The standard guarantees that performing atomic operations on data that is used across multiple threads will not result in a data race. However, direct access to data members of atomic type objects violates this guarantee.

Note. The `atomic_init` function alone does not prevent a potential data race. If multiple threads access a variable at initialization—even when atomic operations are used—it can still cause a race condition.

An example of erroneous code:

    typedef struct {
      int32_t width;
      int32_t height;
    } rectangle_t;

    _Atomic rectangle_t rect;

    int foo(void)
    {
      rect.width = 300;

      return 0;
    }

In the example, directly writing `rect.width = 300;` can cause data races and an invalid object state.

The MISRA guidelines suggest fixing such code as follows:

    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;
    }

However, this fix alone is insufficient. Although the issue of changing non-atomic data members in the structure has been resolved, a new potential synchronization issue has been added.

Let's look at the following scenario:

- The first thread calls the `foo` function and copies the structure to the `tmp` variable.
- While the first thread is changing the `tmp.height` value, the second one can change the `rect.width` value.
- The first thread calls the `atomic_store` function and overwrites `rect.width` with the old value. This is an error.

To avoid this issue, additional synchronization between different threads may be required. However, this topic is beyond the scope of the MISRA diagnostic rule.

This diagnostic is classified as:

MISRA-C-2023-12.6