Udostępnij za pośrednictwem


Ostrzeżenie C26429

Symbol nigdy nie jest testowany pod kątem wartości null. Można go oznaczyć jako gsl::not_null.

Podstawowe wytyczne dotyczące języka C++: F.23: Użyj elementu , not_null<T> aby wskazać, że wartość "null" nie jest prawidłową wartością

Częstą praktyką jest użycie asertów w celu wymuszenia założeń dotyczących ważności wartości wskaźnika. Problem polega na tym, że asercyjnie nie uwidacznia założeń za pośrednictwem interfejsu (np. w zwracanych typach lub parametrach). Potwierdzenia są również trudniejsze do utrzymania i synchronizowania z innymi zmianami kodu. Zaleceniem jest użycie biblioteki gsl::not_null pomocy technicznej wytycznych do oznaczania zasobów, które nigdy nie powinny mieć wartości null. Reguła USE_NOTNULL pomaga zidentyfikować miejsca, w których pominięto sprawdzanie wartości null, dlatego można je zaktualizować tak, aby używały polecenia gsl::not_null.

Uwagi

Logika reguły wymaga, aby kod wyłuszył zmienną wskaźnika, aby sprawdzanie wartości null (lub wymuszanie wartości innej niż null) było uzasadnione. Dlatego ostrzeżenia są emitowane tylko wtedy, gdy wskaźniki są wyłuszczane i nigdy nie testowane pod kątem wartości null.

Bieżąca implementacja obsługuje tylko zwykłe wskaźniki (lub ich aliasy) i nie wykrywa inteligentnych wskaźników, mimo że gsl::not_null można je również zastosować do inteligentnych wskaźników.

Zmienna jest oznaczona jako zaznaczona pod kątem wartości null, gdy jest używana w następujących kontekstach:

  • jako wyrażenie symbolu w warunku gałęzi, na przykład ; if (p) { ... }
  • nie bitowe operacje logiczne;
  • operacje porównania, w których jeden operand jest wyrażeniem stałym, które daje w wyniku zero.

Reguła nie ma pełnego śledzenia przepływu danych. Może ona generować nieprawidłowe wyniki w przypadkach, gdy są używane kontrole pośrednie (na przykład gdy zmienna pośrednia przechowuje wartość null i jest później używana w porównaniu).

Nazwa analizy kodu: USE_NOTNULL

Przykład

Ukryte oczekiwania:

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();
        // ...
    }
}

Ukryte oczekiwania wyjaśnione przez 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();
        // ...
    }
}