Анализатор обнаружил в качестве аргумента оператора '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); }
Данная диагностика классифицируется как: