Sdílet prostřednictvím


Upozornění C26430

Symbol není testován pro nulovost ve všech cestách.

C++ Core Guidelines: F.23: Použití not_null<T> k označení, že hodnota null není platná hodnota

Pokud kód někdy kontroluje proměnné ukazatele na hodnotu null, měl by to provést konzistentně a ověřit ukazatele na všech cestách. Někdy je přeaggresivní kontrola hodnoty null stále lepší než možnost těžkého chybového ukončení v jedné z komplikovaných větví. V ideálním případě by měl být takový kód refaktorován tak, aby byl méně složitý (rozdělením do více funkcí) a spoléhat se na značky jako gsl::not_null. Tyto značky umožňují kódu izolovat části algoritmu, které mohou zajistit bezpečné předpoklady o platných hodnotách ukazatele. Toto pravidlo TEST_ON_ALL_PATHS pomáhá najít místa, kde jsou kontroly null nekonzistentní (což znamená, že předpoklady mohou vyžadovat kontrolu). Nebo najde skutečné chyby, kdy potenciální hodnota null může obejít kontroly null v některých cestách kódu.

Poznámky

Toto pravidlo očekává, že kód překládá proměnnou ukazatele tak, aby byla zakládaná kontrola null (nebo vynucení hodnoty, která není null). Pokud neexistuje žádná dereference, pravidlo se pozastaví.

Aktuální implementace zpracovává pouze prosté ukazatele (nebo jejich aliasy) a nedetekuje inteligentní ukazatele, i když kontroly null platí i pro inteligentní ukazatele.

Proměnná se označí jako zaškrtnutá, pokud se použije v následujících kontextech:

  • jako výraz symbolu v podmínce větve, například v if (p) { ... };
  • v nebitových logických operacích;
  • v operacích porovnání, kde jeden operand je konstantní výraz, který se vyhodnotí na nulu.

Implicitní kontroly null se předpokládají, když je hodnota ukazatele přiřazena z:

  • přidělení prováděné s vyvoláním operator new;
  • ukazatel získaný z typu označeného značkou gsl::not_null.

Příklad

nekonzistentní testování odhalí chybu logiky.

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

nekonzistentní testování odhalí chybu logiky – opraveno

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

Heuristika

Při zajištění, že dereference ukazatele není null, toto pravidlo nevyžaduje , aby každé dereference měla předchozí kontrolu null. Místo toho vyžaduje kontrolu null před prvním dereference ukazatele. Následující funkce neaktivuje C26430:

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

Následující funkce vygeneruje C26430, protože existuje cesta k přiřazení *p bez kontroly null:

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

Pravidla C26822 a C26823 se vztahují na dereferencing ukazatele null (případně).

Toto pravidlo neprovádí úplné sledování toku dat. Může vést k nesprávným výsledkům v případech, kdy se používají nepřímé kontroly, například když zprostředkující proměnná obsahuje hodnotu null a později se použije v porovnání.

Viz také

C26822
C26823