# V1055. The 'sizeof' expression returns the size of the container type, not the number of elements. Consider using the 'size()' function.

Анализатор обнаружил в качестве аргумента оператора 'sizeof' переменную типа "STL-подобный контейнер".

Рассмотрим следующий пример:

    #include <string>

    void foo(const std::string &name)
    {
      auto len = sizeof(name) / sizeof(name[0]);
      ....
    }

Выражение 'sizeof(name)' возвращает не суммарный размер элементов в контейнере в байтах (или просто количество элементов), а именно размер типа контейнера, отведенный для имплементации. Например, типичная имплементация 'std::string' может содержать 3 указателя (стандартная библиотека libc++, 64-битная система), т.е. 'sizeof(name) == 24'. Размер же реальной хранимой строки чаще всего отличается от этого значения.

Ошибка подобного рода может появиться в проекте в результате рефакторинга старого кода:

    #define MAX_LEN(str) ( sizeof((str)) / sizeof((str)[0]) - 1 )
    typedef char MyString[256];

    void foo()
    {
      MyString str { .... };
      ....
      size_t max_len = MAX_LEN(str);
    }

При замене псевдонима 'MyString' с типа 'char[256]' на 'std::string' вычисление максимально допустимой длины строки станет некорректным.

Для получения реального размера STL-подобных контейнеров стоит использовать публичную функцию-член '.size()':

    #include <string>
    void foo(const std::string &name)
    {
      auto len = name.size();
    }

Если подразумевалось именно вычисление размера имплементации контейнера, то для лучшего понимания кода предпочтительнее передавать в качестве операнда оператора 'sizeof' тип контейнера, прямым способом или через оператор 'decltype' (C++11) для переменных:

    #include <string>

    void foo(const std::string &str)
    {
      auto string_size_impl1 = sizeof(std::string);
      auto string_size_impl2 = sizeof(decltype(str));
    }

Диагностика также знает о существовании контейнера 'std::array' и не выдает на нем срабатывание при его использовании в качестве операнда оператора 'sizeof':

    template <typename T, size_t N>
    void foo(const std::array<T, N> &arr)
    {
      auto size = sizeof(arr) / sizeof(arr[0]); // ok
    }

Начиная со стандарта C++17, рекомендуется использовать свободную функцию 'std::size()', которая умеет работать как встроенными массивами, так и всеми типами контейнеров, имеющими публичную функцию-член '.size()':

    #include <vector>
    #include <string>
    #include <set>
    #include <list>

    void foo()
    {
      int arr[256] { .... };

      std::vector vec { .... };
      std::string str { .... };
      std::set    set { .... };
      std::list  list { .... };

      auto len1 = std::size(arr);
      auto len2 = std::size(vec);
      auto len3 = std::size(str);
      auto len4 = std::size(set);
      auto len5 = std::size(list);
    }

Данная диагностика классифицируется как:

CWE-131