Aviso C26448

Considere usar gsl::finally se a ação final for pretendida (gsl.util)

Diretrizes Principais do C++: GSL.util: Utilitários

A Biblioteca de Suporte de Diretrizes fornece um utilitário conveniente para implementar o conceito de ação final. Como a linguagem C++ não dá suporte a constructos try-finally, tornou-se comum implementar tipos de limpeza personalizados que invocam ações arbitrárias sobre destruição. O utilitário gsl::finally é implementado dessa forma e fornece uma maneira mais uniforme de executar ações finais em uma base de código.

Há também casos em que as ações finais são executadas de maneira antiquada no estilo C usando goto instruções (o que é desencorajado pelo C26438 NO_GOTO). É difícil detectar a intenção exata no código que usa gotomuito, mas algumas heurísticas podem ajudar a encontrar melhores candidatos para limpeza.

Comentários

  • Essa regra é leve e usa nomes de rótulo para adivinhar oportunidades de usar objetos de ação finais.
  • Nomes de rótulo que podem gerar um aviso contêm palavras como "end", "final", "clean" e assim por diante.
  • Os avisos aparecem nas instruções goto. Você pode ver uma saída detalhada em algumas ocasiões, mas a saída pode ajudar na priorização do código, dependendo de sua complexidade.
  • Essa regra sempre entra em par com C26438 NO_GOTO. Dependendo das prioridades, uma dessas regras pode ser desativada.

Nome da análise de código: USE_GSL_FINALLY

Exemplo

Limpeza com várias instruções 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();
}

Limpeza com várias instruções goto substituídas por 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;
        // ...
    }
}