Compartilhar via


Aviso C26430

O símbolo não é testado quanto à nulidade em todos os caminhos.

Diretrizes principais do C++: F.23: Use um not_null<T> para indicar que "null" não é um valor válido

Se o código verificar variáveis de ponteiro para nulo, ele deve fazê-lo consistentemente e validar ponteiros em todos os caminhos. Às vezes, a verificação excessivamente agressiva de nulo ainda é melhor do que a possibilidade de um travamento rígido em um dos ramos complicados. Idealmente, esse código deve ser refatorado para ser menos complexo (dividindo-o em várias funções) e para confiar em marcadores como gsl::not_null. Esses marcadores permitem que o código isole partes do algoritmo que podem fazer suposições seguras sobre valores de ponteiro válidos. A regra TEST_ON_ALL_PATHS ajuda a encontrar locais onde verificações nulas são inconsistentes (o que significa que suposições podem exigir revisão). Ou, ele encontra bugs reais onde um valor nulo potencial pode ignorar verificações nulas em alguns dos caminhos de código.

Comentários

Essa regra espera que o código desreferencia uma variável de ponteiro para que uma verificação nula (ou imposição de um valor não nulo) seja justificada. Se não houver desreferência, a regra é suspensa.

A implementação atual lida apenas com ponteiros simples (ou seus aliases) e não detecta ponteiros inteligentes, embora verificações nulas também sejam aplicáveis a ponteiros inteligentes.

Uma variável é marcada como verificada para nula quando é usada nos seguintes contextos:

  • como uma expressão de símbolo em uma condição de ramo, por exemplo, em if (p) { ... };
  • em operações lógicas não bitwise;
  • em operações de comparação em que um operando é uma expressão constante que é avaliada como zero.

A regra não tem controle completo do fluxo de dados. Ele pode produzir resultados incorretos nos casos em que verificações indiretas são usadas (como quando uma variável intermediária contém um valor nulo e é usada posteriormente em uma comparação).

Verificações nulas implícitas são assumidas quando um valor de ponteiro é atribuído de:

  • uma alocação realizada com arremesso operator new;
  • um ponteiro obtido de um tipo marcado com gsl::not_null.

Exemplo

teste inconsistente revela erro lógico

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);
    }
}

teste inconsistente revela erro lógico – corrigido

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);
    }
}