Partilhar 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 precisar verificar se variáveis de ponteiro são nulas, deve fazê-lo de forma consistente e validar os ponteiros em todos os caminhos. Às vezes, a verificação agressiva excessiva de nulos ainda é melhor do que a possibilidade de uma falha crítica em uma das ramificações complicadas. 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 as verificações nulas são inconsistentes (o que significa que as 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.

Observações

Esta 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 deteta ponteiros inteligentes, embora verificações nulas também sejam aplicáveis a ponteiros inteligentes.

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

  • como uma expressão simbólica em uma condição de ramificação, 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.

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

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

Exemplo

testes inconsistentes revelam 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);
    }
}

Testes inconsistentes revelam erro de lógica - 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);
    }
}

Heurística

Ao garantir que uma desreferência de um ponteiro não seja nula, essa regra não exige que cada desreferência tenha uma verificação nula prévia. Em vez disso, é necessário realizar uma verificação de nulo antes da primeira desreferência do ponteiro. A seguinte função não aciona C26430:

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

A função a seguir gera C26430 porque há um caminho para atribuir *p sem uma verificação nula:

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

As regras C26822 e C26823 aplicam-se à desreferenciação de um ponteiro (possivelmente) nulo.

Esta regra não faz o rastreamento completo do fluxo de dados. Pode produzir resultados incorretos nos casos em que são utilizadas verificações indiretas, como quando uma variável intermédia detém um valor nulo e é posteriormente utilizada numa comparação.

Ver também

C26822
C26823