Udostępnij za pośrednictwem


Ostrzeżenie C26448

Rozważ użycie gsl::finally , jeśli ostateczna akcja jest przeznaczona (gsl.util)

Podstawowe wytyczne języka C++: GSL.util: Narzędzia

Biblioteka pomocy technicznej wytycznych udostępnia wygodne narzędzie do implementowania ostatecznej koncepcji akcji . Ponieważ język C++ nie obsługuje konstrukcji try-finally , stało się powszechne implementowanie niestandardowych typów oczyszczania, które wywołują dowolne akcje w przypadku zniszczenia. Narzędzie gsl::finally jest implementowane w ten sposób i zapewnia bardziej jednolity sposób wykonywania ostatecznych akcji w bazie kodu.

Istnieją również przypadki, w których ostateczne akcje są wykonywane w starym stylu C za pomocą goto instrukcji (co jest zniechęcane przez C26438 NO_GOTO). Trudno jest wykryć dokładną intencję w kodzie, który intensywnie używa gotometody , ale niektóre heurystyki mogą pomóc znaleźć lepszych kandydatów do oczyszczenia.

Uwagi

  • Ta reguła jest uproszczona i używa nazw etykiet do odgadnięcia możliwości korzystania z końcowych obiektów akcji.
  • Nazwy etykiet, które mogą zgłaszać ostrzeżenie, zawierają wyrazy takie jak "end", "final", "clean" itd.
  • Ostrzeżenia są wyświetlane w instrukcjach goto . Czasami mogą pojawić się pełne dane wyjściowe, ale dane wyjściowe mogą pomóc w określaniu priorytetów kodu w zależności od jego złożoności.
  • Ta reguła zawsze jest połączona z NO_GOTO C26438. W zależności od priorytetów można wyłączyć jedną z tych reguł.

Nazwa analizy kodu: USE_GSL_FINALLY

Przykład

Czyszczenie za pomocą wielu instrukcji goto:

void poll(connection_info info)
{
    connection c = {};
    if (!c.open(info))
        return;

    while (c.wait())
    {
        connection::header h{};
        connection::signature s{};
        if (!c.read_header(h))
            goto end;               // C26448 and C26438
        if (!c.read_signature(s))
            goto end;               // C26448 and C26438
        // ...
    }

end:
    c.close();
}

Oczyszczanie za pomocą wielu instrukcji goto zastąpionych przez gsl::finally:

void poll(connection_info info)
{
    connection c = {};
    if (!c.open(info))
        return;

    auto end = gsl::finally([&c] { c.close(); });
    while (c.wait())
    {
        connection::header h{};
        connection::signature s{};
        if (!c.read_header(h))
            return;
        if (!c.read_signature(s))
            return;
        // ...
    }
}