경고 C26446

un검사ed subscript 연산자(bounds.4) 대신 gsl::at()를 사용하는 것이 좋습니다.

C++ 핵심 지침: Bounds.4: 경계 검사 아닌 표준 라이브러리 함수 및 형식을 사용하지 마세요.

설명

C++ 핵심 지침의 경계 프로필은 안전하지 않은 메모리 조작을 제거하려고 합니다. 원시 포인터 및 비검사 연산을 사용하지 않도록 방지할 수 있습니다. 버퍼에 대한 균일한 범위 검사 액세스를 수행하는 한 가지 방법은 지침 지원 라이브러리의 gsl::at() 유틸리티를 사용하는 것입니다. 또한 STL 컨테이너에서 사용할 수 있는 표준 구현을 at() 사용하는 것이 좋습니다.

이 규칙은 호출을 통해 잠재적으로 검사 액세스가 수행되는 위치를 찾는 데 operator[]도움이 됩니다. 대부분의 경우 gsl::at().

  • 알려진 크기의 배열에 대한 액세스는 비 상수 인덱스가 아래 첨자 연산자에서 사용될 때 플래그가 지정됩니다. 상수 인덱스는 C26483 STATIC_INDEX_OUT_OF_RANGE 처리됩니다.
  • 오버로드된 operator[] 호출에 대해 경고하는 논리는 더 복잡합니다.
    • 인덱스가 정수가 아니면 호출이 무시됩니다. 또한 이러한 연산자에서 매개 변수가 참조로 전달되므로 표준 맵에서 인덱싱을 처리합니다.
    • 연산자가 throw되지 않는 것으로 표시되면(또는 __declspec(nothrow)사용noexceptthrow()) 호출에 플래그가 지정됩니다. 아래 첨자 연산자가 예외를 throw하지 않는 경우 범위 검사 수행하지 않거나 이러한 검사 모호하다고 가정합니다.
    • 연산자가 throw되지 않는 것으로 표시되지 않으면 기존 at() 멤버 함수를 정의하는 STL 컨테이너에서 가져온 경우 플래그가 지정될 수 있습니다. 이러한 함수는 간단한 이름 일치를 통해 검색됩니다.
    • 규칙은 표준 at() 함수 호출에 대해 경고하지 않습니다. 이러한 함수는 안전합니다. 그들을 교체하는 gsl::at() 것은 많은 가치를 가져다주지 않습니다.
  • 인덱싱 std::basic_string_view<> 이 안전하지 않으므로 경고가 발생합니다. 항상 경계 검사 사용해서 gsl::basic_string_span<>표준을 string_view 바꿉니다.
  • 구현에서는 사용자 코드가 루프 또는 분기의 어딘가에 있을 수 있는 범위 검사 고려하지 않습니다. 여기서 정확도는 성능을 위해 거래됩니다. 일반적으로 더 신뢰할 수 있는 반복기 또는 더 간결하게 향상된 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';
}