Предупреждение C26449
gsl::span
илиstd::string_view
создается из временного экземпляра, если временное недопустимое значение (gsl.view)
Основные рекомендации по C++ : GSL.view: представления.
Диапазоны и представления являются удобными и упрощенными типами, которые позволяют ссылаться на буферы памяти. Но их следует тщательно использовать: хотя их интерфейс выглядит аналогично стандартным контейнерам, их поведение больше похоже на поведение указателей и ссылок. Они не имеют собственных данных и никогда не должны быть созданы из временных буферов. Эта проверка фокусируется на случаях, когда исходные данные являются временными, в то время как диапазон или представление не является. Это правило может помочь избежать тонких, но опасных ошибок, сделанных при модернизации устаревшего кода и принятия диапазонов или представлений. Существует еще одна проверка, которая обрабатывает немного другой сценарий, включающий ссылки на диапазон: C26445 NO_SPAN_REF.
Рассмотрите возможность использования C26815 и C26816. Эти предупреждения являются более общими версиями этого предупреждения.
Замечания
Это правило предупреждает о местах, где конструкторы вызываются для диапазонов или представлений, а буфер исходных данных принадлежит временному объекту, созданному в той же инструкции. Эта проверка включает:
- неявные преобразования в операторах return;
- неявные преобразования в тернарных операторах;
- явные преобразования в
static_cast
выражениях; - вызовы функций, возвращающие контейнеры по значению.
Временные элементы, созданные для аргументов вызова функции, не помечены. Это безопасно для передачи диапазонов от таких временных элементов, если целевые функции не сохраняют указатели данных во внешних переменных.
Если диапазоны или представления являются временными, правило пропускает их.
Отслеживание данных в средство проверки имеет определенные ограничения; поэтому сложные сценарии, связанные с несколькими или неясными переназначениями, могут не обрабатываться.
Имя анализа кода: NO_SPAN_FROM_TEMPORARY
Пример
Тонкое различие в типах результатов:
// Returns a predefined collection. Keeps data alive.
gsl::span<const sequence_item> get_seed_sequence() noexcept;
// Returns a generated collection. Doesn't own new data.
std::vector<sequence_item> get_next_sequence(gsl::span<const sequence_item>);
void run_batch()
{
auto sequence = get_seed_sequence();
while (send(sequence))
{
sequence = get_next_sequence(sequence); // C26449
// ...
}
}
Чтобы устранить проблему, убедитесь, что представление создается из объекта, который живет по крайней мере до самого представления. Иногда решение может быть достигнуто путем копирования данных, в других случаях необходимо изменить некоторые API для совместного использования ссылки на объект, который живет достаточно долго, а не возвращать временную копию.