Condividi tramite


Avviso C26438

Evitare goto (es.76)

Linee guida di base per C++:
ES.76: Evitare goto

L'uso di goto è ampiamente considerato una pratica pericolosa e soggetta a errori. È accettabile solo nel codice generato, ad esempio in un parser generato da una grammatica. Con le funzionalità e le utilità C++ moderne fornite dalla libreria di supporto delle linee guida, dovrebbe essere facile evitare goto del tutto.

Osservazioni:

  • Questa regola avvisa su qualsiasi occorrenza di goto, anche se si verifica in codice non attivo, ad eccezione del codice modello che non viene mai usato e quindi viene ignorato dal compilatore.
  • Gli avvisi possono moltiplicarsi quando una macro contiene goto. I meccanismi di creazione di report correnti puntano a tutte le istanze in cui tale macro viene espansa. Spesso può essere corretto in un'unica posizione modificando la macro o evitandone l'uso a favore di meccanismi più gestibili.

Nome dell'analisi del codice: NO_GOTO

Esempio

'goto clean-up' nella macro

#define ENSURE(E, L) if (!(E)) goto L;

void poll(connection &c)
{
    ENSURE(c.open(), end);                  // C26438

    while (c.wait())
    {
        connection::header h{};
        connection::signature s{};
        ENSURE(c.read_header(h), end);      // C26438
        ENSURE(c.read_signature(s), end);   // C26438
        // ...
    }

end:
    c.close();
}

'goto clean-up' in macro, sostituito con gsl::finally

void poll(connection &c)
{
    auto end = gsl::finally([&c] { c.close(); });

    if (!c.open())
        return;

    while (c.wait())
    {
        connection::header h{};
        connection::signature s{};
        if(!c.read_header(h))
            return;
       if(!c.read_signature(s))
            return;
        // ...
    }
}