Поделиться через


Предупреждение 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 для совместного использования ссылки на объект, который живет достаточно долго, а не возвращать временную копию.

См. также

C26815
C26816