C++ 프로그래밍

C++ 전역 객체 혹은 정적 객체 간의 생성 및 소멸 순서 문제

하늘흐늘 2021. 12. 9. 20:09
반응형

C++에서 전역 객체 혹은 정적 객체들의 생성과 소멸 순서는 따로 규칙이 정해져 있지 않습니다. 
C++ 전역 혹은 정적 객체 생성에 관해서 정해져 있는 것은 초기화 이전에 0으로 초기화 된다는 것 뿐입니다. 그 외에 메인의 첫 문장 실행 전에 지역 변수가 아닌 정적 변수가 초기화될 것인지 여부는 컴파일 구현에 따라 틀립니다. 

이런 세세한 것을 알아야 하는 이유는 전역 혹은 정적 객체간에 직접적 혹은 간접적으로 참조를 하는 경우에 문제가 생길 수 있기 때문입니다. 
한 예로 전역 변수 A가 정적 변수 B를 호출하는데 생성 및 초기화 순서에 따라 전역 변수 A는 초기화 되지 않는 정적 변수 B를 호출할 수 있습니다. 이런 경우 프로그램이 멈추거나 잘못된 값을 가지는 알 수 없는 상황이 발생하게 됩니다. 
또 다른 예로 전역 변수 A가 정적 변수 B를 참조하는데 프로그램이 종료되어 소멸될 때 전역 변수 A가 소멸자에서 소멸된 정적 변수 B를 호출 할 수도 있습니다. C++은 소멸된 객체의 멤버 함수도 호출이 가능하며 변수가 깨지지 않는 이상 알 수 없는 결과가 나올 뿐입니다. 

생성 순서에 대한 문제 해결 방법은 전역 객체 혹은 정적 객체 간에 참조할 때 생성자에서 참조 하는 것을 막고 init 함수와 같이 생성된 뒤에 호출하는 함수를 통하여 참조가 되도록 수정하는 것입니다. 이 경우에는 생성이 정상적으로 이루어진 후에 호출되는 것이기 때문에 참조하는 객체도 이상없이 초기화가 되어 있을 것입니다. 
소멸 순서에 대한 문제 해결 방법은 참조하는 쪽에서 참조하지 않도록 수정하는 것이 좋습니다. 그렇지만 부득이하게 호출되는 함수가 소멸된 객체에 대하여 함수를 호출하는 경우 임시적으로 해당 함수에서 이상하게 동작하지 않고 바로 리턴하도록 방어적으로 코드를 작성하여야 합니다. 물론 이런 경우는 소멸된 객체에 대한 함수 호출이 일어나지 않도록 구조를 변경해야 합니다.

어떻게 보면 싱글톤을 사용하는 것이 하나의 해결책이 될 수도 있습니다. 유지 보수하기가 불편할 수도 있지만, 싱글톤은 특성상 싱글톤들의 하나의 초기화 함수와 하나의 종료 함수를 두어 초기화와 종료의 순서를 제어할 수 있습니다. 

마지막으로 이런 문제와 관련하여 찾아본 아래 내용도 참고 바랍니다.
Static member object initialization failure

반응형