C++에서는 전역 및 정적 객체가 main() 함수에 들어가기 전에 초기화됩니다. 그러나 표준은 다른 번역 단위에 있는 객체들 간의 초기화 순서를 보장하지 않습니다. 이는 하나의 전역 객체가 다른 객체를 참조하고 그 객체가 아직 초기화되지 않은 상태에서 발생하는 이른바 "정적 초기화 순서 실패"라는 버그로 이어질 수 있습니다.
올바른 초기화를 보장하고 문제를 피하기 위해 "처음 사용할 때 생성하기" 패턴을 사용합니다: 정적 지역 객체에 대한 참조를 반환하는 함수를 선언합니다(이 객체는 C++11에서 첫 번째 호출 시 스레드 안전하게 생성됩니다).
// foo.h class Config { public: int value; }; Config& getConfig() { static Config config; config.value = 42; // 초기화가 보장됩니다! return config; }
서로 다른 두 .cpp 파일에서 전역 객체가 서로를 생성하면 어떻게 될까요?
답변: 결과는 정의되지 않으며, 초기화되지 않은 객체에 접근하는 일이 발생할 수 있습니다. 해결책은 함수 내에서 정적 지역 객체를 통한 지연 초기화로 직접적인 전역 초기화를 대체하는 것입니다 (위 참조).
이야기
-CRM 시스템에서 두 모듈이 서로를 참조하는 전역 로거를 선언했습니다. 서로 다른 애플리케이션 빌드에서 초기화 순서가 변경되어, 잡기 어려운 버그가 발생했습니다: 충돌 및 null 포인터에 대한 로깅.
이야기
-그래픽 엔진에서 전역 자원 컨테이너 객체가 글로벌 자원 관리자를 참조했습니다. Linux와 Windows 환경에서 컴파일러가 로드 순서를 다르게 구현하여 비동기화와 다양한 충돌이 발생했습니다.
이야기
-개발자가 설정의 전역 초기화를 도입했고, 이후 동료가 설정에 의존하는 또 다른 전역 변수를 추가했습니다. 이는 로컬에서는 잘 작동했지만, CI에서는 모듈의 다른 컴포지션으로 인해 고장이 발생했습니다.