Поделиться через


Предупреждение C26446

Предпочитайте использовать gsl::at() вместо снятого оператора подстрока (bounds.4).

Основные рекомендации по C++ : Bounds.4. Не используйте функции и типы стандартной библиотеки, которые не проверяются.

Замечания

Профиль Bounds основного руководства C++ пытается устранить небезопасные манипуляции с памятью. Это помогает избежать использования необработанных указателей и снятых операций. Одним из способов обеспечения единообразного доступа к буферам является использование gsl::at() служебной программы из библиотеки поддержки рекомендаций. Кроме того, рекомендуется использовать стандартные реализации, доступные в контейнерах at() STL.

Это правило помогает найти места, где потенциально снятый доступ выполняется с помощью вызовов operator[]. В большинстве случаев такие вызовы можно заменить с помощью gsl::at().

  • Доступ к массивам известного размера помечается при использовании неконстантного индекса в операторе подстрока. Константные индексы обрабатываются STATIC_INDEX_OUT_OF_RANGE C26483.
  • Логика предупреждения о перегруженных operator[] вызовах является более сложной:
    • Если индекс не является целочисленным, вызов игнорируется. Это также обрабатывает индексирование в стандартных картах, так как параметры в таких операторах передаются по ссылке.
    • Если оператор помечается как неисключаемый (с помощью noexceptthrow()или__declspec(nothrow)), вызов помечается. Предположим, что если оператор подстрока никогда не создает исключения, он либо не выполняет проверки диапазона, либо эти проверки не являются неясными.
    • Если оператор не помечается как неисполнение, он может быть помечен, если он поступает из контейнера STL, который также определяет обычную at() функцию-член. Такие функции обнаруживаются простым сопоставлением имен.
    • Правило не предупреждает о вызовах стандартных at() функций. Эти функции безопасны; замена их gsl::at() не принесет большого значения.
  • Индексирование std::basic_string_view<> в небезопасное, поэтому выдается предупреждение. Замените стандарт string_view с помощью gsl::basic_string_span<>функции , которая всегда проверяет границы.
  • Реализация не считает, что код пользователя может быть где-то в циклах или ветвях. Здесь точность торгуется на производительность. Как правило, часто можно заменить явные проверки диапазона с помощью более надежных итераторов или более кратких расширенных forциклов ..

Пример

В этом примере показано, как gsl::at функция может заменить индексированную ссылку:

// 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';
}