Compartir vía


Advertencia C26430

El símbolo no se prueba para obtener su valor null en todas las rutas de acceso.

C++ Core Guidelines: F.23: Uso de un elemento not_null<T> para indicar que "null" no es un valor válido

Si el código comprueba alguna vez la obtención de un valor null de las variables de puntero, debe hacerlo de forma coherente y validar punteros en todas las rutas de acceso. A veces, la comprobación excesiva de obtención de un valor null es aún mejor que la posibilidad de un bloqueo importante en una de las ramas complicadas. Idealmente, este código debe refactorizarse para que sea menos complejo (dividiéndolo en varias funciones) y para depender de marcadores como gsl::not_null. Estos marcadores permiten que el código aísle partes del algoritmo que pueden hacer suposiciones seguras sobre los valores de puntero válidos. La regla TEST_ON_ALL_PATHS ayuda a encontrar lugares donde las comprobaciones de valores null son incoherentes (lo que significa que las suposiciones pueden requerir revisión). O bien, encuentra errores reales en los que un posible valor null puede omitir comprobaciones de valores null en algunas de las rutas de acceso de código.

Comentarios

Esta regla espera que el código desreferencie una variable de puntero para que se justificara la comprobación de obtención de un valor null (o la aplicación de un valor distinto de null). Si no hay ninguna desreferencia, se suspende la regla.

La implementación actual solo controla punteros sin formato (o sus alias) y no detecta punteros inteligentes aunque también se apliquen comprobaciones de obtención de un valor null a punteros inteligentes.

Una variable se marca como comprobada para ver si tiene valores null cuando se usa en los contextos siguientes:

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

Se asumen comprobaciones implícitas de obtención de un valor null cuando se asigna un valor de puntero desde lo siguiente:

  • una asignación realizada con la generación de operator new;
  • Un puntero obtenido de un tipo marcado con gsl::not_null.

Ejemplo

Las pruebas incoherentes revelan el error de lógica

void merge_states(const state *left, const state *right) // C26430
{
    if (*left && *right)
        converge(left, right);
    else
    {
        // ...
        if (!left && !right)                            // Logic error!
            discard(left, right);
    }
}

Las pruebas incoherentes revelan un error lógico: corregido

void merge_states(gsl::not_null<const state *> left, gsl::not_null<const state *> right)
{
    if (*left && *right)
        converge(left, right);
    else
    {
        // ...
        if (*left && *right)
            discard(left, right);
    }
}

Heurística

Al asegurarse de que una desreferencia de un puntero no sea null, esta regla no requiere que cada desreferencia tenga una comprobación previa de obtención de valores null. En su lugar, requiere una comprobación de obtención de valores null antes de la primera desreferencia del puntero. La función siguiente no desencadena C26430:

void f(int* p)
{
    if (p)
        *p = 1;
    *p = 2;
}

La función siguiente genera la advertencia C26430 porque hay una ruta de acceso para asignar *p sin una comprobación de obtención de valores null:

void f(bool b, int* p)
{
    if (b && p)
        *p = 1;
    *p = 2;
}

Las reglas C26822 y C26823 se aplican a la desreferenciación de un (posiblemente) puntero nulo.

Esta regla no realiza el seguimiento completo del flujo de datos. Puede generar resultados incorrectos en los casos en los que se usan comprobaciones indirectas, como cuando una variable intermedia contiene un valor null y se usa más adelante en una comparación.

Consulte también

C26822
C26823