Aviso C26449
gsl::span
oustd::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.