Sdílet prostřednictvím


Upozornění C26448

Zvažte použití gsl::finally , pokud je zamýšlená konečná akce (gsl.util).

C++ Core Guidelines: GSL.util: Nástroje

Knihovna podpory pokynů poskytuje pohodlný nástroj pro implementaci konečného konceptu akce . Vzhledem k tomu, že jazyk C++ nepodporuje konstrukce try-finally , začal se běžně implementovat vlastní typy čištění, které by vyvolaly libovolné akce na zničení. Nástroj gsl::finally je implementovaný tímto způsobem a poskytuje jednotnější způsob provádění konečných akcí v základu kódu.

Existují také případy, kdy se konečné akce provádějí starým způsobem stylu jazyka C pomocí goto příkazů (které nedoporučuje C26438 NO_GOTO). Je těžké rozpoznat přesný záměr v kódu, který silně používá goto, ale některé heuristické můžou pomoci najít lepší kandidáty na vyčištění.

Poznámky

  • Toto pravidlo je jednoduché a používá názvy popisků k odhadování příležitostí k použití konečných objektů akce.
  • Názvy popisků, které můžou vyvolat upozornění, obsahují slova jako "end", "final", "clean" atd.
  • V příkazech se zobrazí goto upozornění. V některých případech se může zobrazit podrobný výstup, ale výstup může pomoct určit prioritu kódu v závislosti na jeho složitosti.
  • Toto pravidlo se vždy spojí s NO_GOTO C26438. V závislosti na prioritách může být některá z těchto pravidel zakázaná.

Název analýzy kódu: USE_GSL_FINALLY

Příklad

Vyčištění pomocí několika příkazů 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();
}

Vyčištění s více příkazy goto nahrazeno 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;
        // ...
    }
}