Compartir vía


Advertencia C26429

El símbolo nunca se prueba para el valor nullness, se puede marcar como gsl::not_null.

Directrices básicas de C++: F.23: Use para not_null<T> indicar que "null" no es un valor válido

Es una práctica habitual usar aserciones para aplicar suposiciones sobre la validez de los valores de puntero. El problema es que las aserciones no exponen suposiciones a través de la interfaz (por ejemplo, en tipos de valor devuelto o parámetros). Las aserciones también son más difíciles de mantener y mantener sincronizadas con otros cambios de código. La recomendación es usar gsl::not_null desde la Biblioteca de soporte técnico de directrices para marcar los recursos que nunca deben tener un valor NULL. La regla USE_NOTNULL ayuda a identificar lugares que omiten comprobaciones de null y, por tanto, se pueden actualizar para usar gsl::not_null.

Comentarios

La lógica de la regla requiere código para desreferenciar una variable de puntero para que se justificara una comprobación nula (o la aplicación de un valor distinto de NULL). Por lo tanto, las advertencias solo se emiten si los punteros se desreferencian y nunca se prueban para null.

La implementación actual solo controla punteros sin formato (o sus alias) y no detecta punteros inteligentes, aunque gsl::not_null también se pueda aplicar a punteros inteligentes.

Una variable se marca como activada como null cuando se usa en los contextos siguientes:

  • como expresión de símbolo en una condición de rama, por ejemplo, if (p) { ... };
  • Operaciones lógicas que no son bit a bit;
  • Operaciones de comparación en las que un operando es una expresión constante que se evalúa como cero.

La regla no tiene seguimiento completo del flujo de datos. Puede generar resultados incorrectos en los casos en los que se usan comprobaciones indirectas (por ejemplo, cuando una variable intermedia contiene un valor NULL y se usa más adelante en una comparación).

Nombre del análisis de código: USE_NOTNULL

Ejemplo

Expectativa oculta:

using client_collection = gsl::span<client*>;
// ...
void keep_alive(const connection *connection)   // C26429
{
    const client_collection clients = connection->get_clients();
    for (ptrdiff_t i = 0; i < clients.size(); i++)
    {
        auto client = clients[i];               // C26429
        client->send_heartbeat();
        // ...
    }
}

Expectativa oculta aclarada por gsl::not_null:

using client_collection = gsl::span<gsl::not_null<client*>>;
// ...
void keep_alive(gsl::not_null<const connection*> connection)
{
    const client_collection clients = connection->get_clients();
    for (ptrdiff_t i = 0; i < clients.size(); i++)
    {
        auto client = clients[i];
        client->send_heartbeat();
        // ...
    }
}