# V117. Memsize type is used in the union.

Анализатор обнаружил потенциально возможную ошибку, связанную с использованием memsize внутри объединения (union). Ошибка может возникнуть при работе с такими объединениями без учета изменения размеров memsize типов на 64-битной системе.

Следует внимательно относиться к объединениям, имеющим в своем составе указатели и другие члены типа memsize.

Первый пример.

Иногда возникает необходимость работать с указателем, как с целым числом. Приведенный в примере код удобен тем, что для работы с числовым представлением указателя не используются явные приведения типов.

    union PtrNumUnion {
      char *m_p;
      unsigned m_n;
    } u;
    ...
    u.m_p = str;
    u.m_n += delta;

'm_n' на 64-битной системе, мы работаем только с частью указателя 'm_p'. Следует использовать тип, который будет соответствовать размеру указателя, как показано ниже.

    union PtrNumUnion {
      char *m_p;
      size_t m_n; //type fixed
    } u;

Второй пример.

Другое частое использование объединения заключается в представлении одного члена, набором других более мелких. Например, нам может потребоваться разбить значение типа 'size_t' на байты для реализации табличного алгоритма подсчета количества нулевых битов в байте.

    union SizetToBytesUnion {
      size_t value;
      struct {
        unsigned char b0, b1, b2, b3;
      } bytes;
    } u;

    SizetToBytesUnion u;
    u.value = value;
    size_t zeroBitsN = TranslateTable[u.bytes.b0] +
                       TranslateTable[u.bytes.b1] +
                       TranslateTable[u.bytes.b2] +
                       TranslateTable[u.bytes.b3];

Здесь допущена принципиальная алгоритмическая ошибка, заключающаяся в предположении, что тип 'size_t' состоит из 4 байт. Возможность автоматического поиска алгоритмических ошибок на данном этапе развития статических анализаторов не возможна, но осуществляет поиск всех объединений, в которых присутствуют memsize типы. Просмотрев список таких потенциально опасных объединений, пользователь может обнаружить логические ошибки. Найдя приведенное в примере объединение, пользователь может обнаружить алгоритмическую ошибку и переписать код следующим образом.

    union SizetToBytesUnion {
      size_t value;
      unsigned char bytes[sizeof(value)];
    } u;

    SizetToBytesUnion u;
    u.value = value;
    size_t zeroBitsN = 0;
    for (size_t i = 0; i != sizeof(u.bytes); ++i)
      zeroBitsN += TranslateTable[u.bytes[i]];

Родственным диагностическим сообщением является V122.

Дополнительные материалы по данной теме:

- 64-битные уроки. Урок 16. Паттерн 8. Memsize-типы в объединениях.