Advertencia C26449
gsl::span
ostd::string_view
se crea a partir de un valor temporal no será válido cuando el valor temporal se invalide (gsl.view)
C++ Core Guidelines: GSL.view: Vistas.
Los intervalos y vistas son tipos cómodos y ligeros que permiten hacer referencia a búferes de memoria. Pero se deben usar con precaución: mientras que su interfaz es similar a los contenedores estándar, su comportamiento se parece más al de los punteros y referencias. No poseen datos y nunca se deben construir a partir de búferes temporales. Esta comprobación se centra en los casos en los que los datos de origen son temporales, mientras que un intervalo o vista no lo son. Esta regla puede ayudar a evitar errores sutiles pero peligrosos que se cometen cuando el código heredado se moderniza y adopta intervalos o vistas. Hay otra comprobación que controla un escenario ligeramente diferente que implica referencias de intervalo: C26445 NO_SPAN_REF.
Considere la posibilidad de usar C26815 y C26816. Esas advertencias son versiones más generales de esta advertencia.
Comentarios
Esta regla advierte de aquellos lugares en que se invocan constructores en intervalos o vistas, y el búfer de datos de origen pertenece a un objeto temporal creado en la misma instrucción. Esta comprobación incluye:
- conversiones implícitas en instrucciones "return";
- conversiones implícitas en operadores ternarios;
- conversiones explícitas en expresiones
static_cast
; - llamadas de función que devuelven contenedores por valor.
No se marcan los temporalmente creados para los argumentos de llamada de función. Es seguro pasar intervalos de tales temporales si las funciones de destino no conservan punteros de datos en variables externas.
Si los intervalos o las vistas ya son temporales, la regla los omite.
El seguimiento de datos en el comprobador tiene ciertas limitaciones; por lo tanto, es posible que no se controlen escenarios complejos que impliquen reasignaciones múltiples o ocultas.
Nombre del análisis de código: NO_SPAN_FROM_TEMPORARY
Ejemplo
Diferencia sutil en los 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 corregir el problema, asegúrese de que la vista se crea a partir de un objeto que reside al menos siempre que la propia vista. A veces, se puede lograr una solución copiando los datos, otras veces es necesario rediseñar algunas API para compartir una referencia a un objeto que vive lo suficiente en lugar de devolver una copia temporal.