경고 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;
}