Partilhar via


Aviso C26446

Prefira usar gsl::at() em vez do operador subscrito não verificado (bounds.4).

Diretrizes principais do C++: Bounds.4: Não use funções e tipos de biblioteca padrão que não estejam com limites verificados.

Observações

O perfil Bounds das C++ Core Guidelines tenta eliminar manipulações inseguras de memória. Ele ajuda a evitar o uso de ponteiros brutos e operações não verificadas. Uma maneira de executar o acesso uniforme verificado por intervalo a buffers é usar o gsl::at() utilitário da Biblioteca de Suporte de Diretrizes. Também é uma boa prática confiar em implementações padrão de at() disponíveis em contêineres STL.

Esta regra ajuda a encontrar locais onde o acesso potencialmente não verificado é realizado através de chamadas para operator[]. Na maioria dos casos, você pode substituir essas chamadas usando gsl::at().

  • O acesso a matrizes de tamanho conhecido é sinalizado quando um índice não constante é usado em um operador subscrito. Os índices constantes são tratados por C26483 STATIC_INDEX_OUT_OF_RANGE.
  • A lógica para avisar sobre chamadas sobrecarregadas operator[] é mais complexa:
    • Se o índice não for integral, a chamada será ignorada. Isso também lida com a indexação em mapas padrão, uma vez que os parâmetros em tais operadores são passados por referência.
    • Se o operador estiver marcado como não lançando (usando noexcept, throw(), ou __declspec(nothrow)), a chamada será sinalizada. Assumimos que, se o operador subscrito nunca lançar exceções, ele não executa verificações de intervalo ou essas verificações são obscuras.
    • Se o operador não estiver marcado como não lançador, ele pode ser sinalizado se vier de um contêiner STL que também define uma função de membro convencional at() . Tais funções são detetadas por simples correspondência de nomes.
    • A regra não avisa em chamadas para funções padrão at() . Estas funções são seguras; substituí-los por gsl::at() não traria muito valor.
  • A indexação em std::basic_string_view<> não é segura, por isso é emitido um aviso. Substitua o padrão string_view usando gsl::basic_string_span<>, que é sempre verificado com limites.
  • A implementação não considera verificações de intervalo que o código do usuário pode ter em algum lugar em loops ou ramificações. Aqui, a precisão é trocada pelo desempenho. Em geral, muitas vezes você pode substituir verificações de intervalo explícitas usando iteradores mais confiáveis ou loops aprimorados formais concisos.

Exemplo

Este exemplo demonstra como a gsl::at função pode substituir uma referência indexada:

// C26446.cpp
#include <vector>
#include <gsl/gsl_util>
#include <iostream>

void fn()
{
    std::vector<int> v{1, 2, 3, 4, 5};
  
    // Normal bracket operators do not prevent you from accessing memory out of bounds.
    std::cout << v[5] << '\n';  // C26446, prefer using gsl::at instead of using operator[].
  
    // gsl::at prevents accessing memory out of bounds and invokes std::terminate on access.
    std::cout << gsl::at(v, 5) << '\n';
}