다음을 통해 공유


경고 C26426

전역 이니셜라이저는 비 constexpr 함수 'symbol'(i.22)을 호출합니다.

C++ Core Guidelines

I.22: 전역 개체의 복잡한 초기화 방지

전역 개체에 대한 이니셜라이저 실행 순서가 일관되지 않거나 정의되지 않을 수 있으므로 재현하고 조사하기 어려운 문제가 발생할 수 있습니다. 이러한 문제를 방지하기 위해 전역 이니셜라이저는 런타임에 실행되는 외부 코드에 의존해서는 안 되며 아직 초기화되지 않은 데이터에 따라 달라질 수 있습니다. 이 규칙은 전역 개체가 함수를 호출하여 초기 값을 가져오는 경우에 플래그를 지정합니다.

설명

  • 규칙은 이러한 호출 constexpr 이 컴파일 시간에 계산되거나 런타임에 예측 가능한 실행을 보장한다는 가정 하에 함수 또는 내장 함수에 대한 호출을 무시합니다.

  • 인라인 함수에 대한 호출은 여전히 플래그가 지정됩니다. 검사기가 구현을 분석하려고 시도하지 않기 때문에 플래그가 지정됩니다.

  • 이 규칙은 사용자 정의 형식(또는 표준 컨테이너)의 변수가 전역적으로 초기화되는 많은 일반적인 시나리오에서 시끄러울 수 있습니다. 생성자 및 소멸자에 대한 호출로 인해 발생하는 경우가 많습니다. 예측할 수 없는 동작이 존재하거나 외부 코드의 향후 변경으로 인해 불안정이 발생할 수 있는 위치를 가리키기 때문에 여전히 유효한 경고입니다.

  • 정적 클래스 멤버는 전역으로 간주되므로 이니셜라이저도 확인됩니다.

코드 분석 이름: NO_GLOBAL_INIT_CALLS

예제

외부 버전 확인:

// api.cpp
int api_version = API_DEFAULT_VERSION; // Assume it can change at run time, hence non-const.
int get_api_version() noexcept {
    return api_version;
}

// client.cpp
int get_api_version() noexcept;
bool is_legacy_mode = get_api_version() <= API_LEGACY_VERSION; // C26426, also stale value

외부 버전 검사를 통해 더 안정적으로 수행되었습니다.

// api.cpp
int& api_version() noexcept {
    static auto value = API_DEFAULT_VERSION;
    return value;
}
int get_api_version() noexcept {
    return api_version();
}

// client.cpp
int get_api_version() noexcept;
bool is_legacy_mode() noexcept {
    return get_api_version() <= API_LEGACY_VERSION;
}