Aviso C26449

gsl::span ou std::string_view criado a partir de um temporário será inválido quando o temporário for invalidado (gsl.view)

Diretrizes Principais do C++: GSL.view: Exibições.

Espaçamentos e visualizações são tipos convenientes e leves que permitem fazer referência a buffers de memória. Mas eles devem ser usados com cuidado: embora sua interface seja semelhante aos contêineres padrão, seu comportamento é mais parecido com o comportamento de ponteiros e referências. Eles não possuem dados e nunca devem ser construídos a partir de buffers temporários. Essa verificação se concentra nos casos em que os dados de origem são temporários, enquanto uma extensão ou exibição não é. Essa regra pode ajudar a evitar erros sutis, mas perigosos, cometidos quando o código herdado é modernizado e adota extensões ou exibições. Há outra verificação que lida com um cenário ligeiramente diferente envolvendo referências de extensão: C26445 NO_SPAN_REF.

Considere o uso de C26815 e C26816. Esses avisos são versões mais gerais desse aviso.

Comentários

  • Essa regra avisa sobre locais em que construtores são invocados para intervalos ou exibições e o buffer de dados de origem pertence a um objeto temporário criado na mesma instrução. Esta verificação inclui:

    • conversões implícitas em instruções return;
    • conversões implícitas em operadores ternários;
    • conversões explícitas em expressões static_cast;
    • chamadas de função que retornam contêineres por valor.
  • Os temporários criados para argumentos de chamada de função não são sinalizados. É seguro passar extensões desses temporários se as funções de destino não retiverem ponteiros de dados em variáveis externas.

  • Se os intervalos ou as exibições forem temporários, a regra os ignorará.

  • O controle de dados no verificador tem certas limitações; portanto, cenários complexos envolvendo reatribuições múltiplas ou obscuras podem não ser identificados.

Nome da análise de código: NO_SPAN_FROM_TEMPORARY

Exemplo

Diferença sutil nos tipos de resultado:

// 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
        // ...
    }
}

Para corrigir o problema, verifique se o modo de exibição foi criado a partir de um objeto que vive pelo menos o mesmo tempo que o próprio modo de exibição. Às vezes, uma solução pode ser obtida copiando os dados, outras vezes algumas APIs precisam ser reprojetadas para compartilhar uma referência a um objeto que vive o suficiente em vez de retornar uma cópia temporária.

Confira também

C26815
C26816