--- title: Warning C26446 description: "Microsoft C++ Code Analysis warning C26446 for the C++ Core Guidelines case Bounds.4." ms.date: 08/21/2010 f1_keywords: ["C26446", "USE_GSL_AT"] helpviewer_keywords: ["C26446"] --- # Warning C26446 > Prefer to use gsl::at() instead of unchecked subscript operator (bounds.4). C++ Core Guidelines: [Bounds.4: Don't use standard-library functions and types that are not bounds-checked](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#probounds-bounds-safety-profile). ## Remarks The Bounds profile of the C++ Core Guidelines tries to eliminate unsafe manipulations of memory. It helps you avoid the use of raw pointers and unchecked operations. One way to perform uniform range-checked access to buffers is to use the `gsl::at()` utility from the Guidelines Support Library. It's also a good practice to rely on standard implementations of `at()` available in STL containers. This rule helps to find places where potentially unchecked access is performed via calls to `operator[]`. In most cases, you can replace such calls by using `gsl::at()`. - Access to arrays of known size is flagged when a non-constant index is used in a subscript operator. Constant indices are handled by [C26483 STATIC_INDEX_OUT_OF_RANGE](c26483.md). - The logic to warn on overloaded `operator[]` calls is more complex: - If the index is non-integral, the call is ignored. This also handles indexing in standard maps, since parameters in such operators are passed by reference. - If the operator is marked as non-throwing (by using **`noexcept`**, **`throw()`**, or **`__declspec(nothrow)`**), the call is flagged. We assume that if the subscript operator never throws exceptions, it either doesn't perform range checks or these checks are obscure. - If the operator isn't marked as non-throwing, it may be flagged if it comes from an STL container that also defines a conventional `at()` member function. Such functions are detected by simple name matching. - The rule doesn't warn on calls to standard `at()` functions. These functions are safe; replacing them with `gsl::at()` wouldn't bring much value. - Indexing into `std::basic_string_view<>` is unsafe, so a warning is issued. Replace the standard `string_view` by using `gsl::basic_string_span<>`, which is always bounds-checked. - The implementation doesn't consider range checks that user code may have somewhere in loops or branches. Here, accuracy is traded for performance. In general, you can often replace explicit range checks by using more reliable iterators or more concise enhanced **`for`**-loops. ## Example This example demonstrates how the `gsl::at` function can replace an indexed reference: ```cpp // C26446.cpp #include #include #include void fn() { std::vector 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'; } ```