4

section 10.13 of the C++ FAQ Lite에 설명 된 정적 초기화 실패를 피하는 간단하고 잘 알려진 패턴이 있습니다.소멸자가 부작용이 있고 객체가 다른 정적 객체의 소멸자에서 액세스되는 경우 정적 초기화를 수행하는 방법은 무엇입니까?

이 표준 패턴에서는 생성 된 객체가 절대로 파괴되지 않습니다 (소멸자가 중요한 부작용이없는 경우에는 문제가되지 않음) 또는 정적 객체가 안전하게 액세스 할 수 없다는 점에서 트레이드 오프가 있습니다 다른 정적 객체의 소멸자 (section 10.14 of the C++ FAQ Lite 참조).

그래서 내 질문은 : 정적 개체의 소멸자가 결국 발생해야하는 중요한 부작용이있는 경우 어떻게 정적 초기화 불능을 피할 수 있습니까? 다른 정적 개체의 소멸자가 액세스해야합니다?


(참고 : 자주 묻는 질문 라이트는이 질문 C++ 자주 묻는 질문의 자주 묻는 질문 16.17에 대한 답변 언급한다. M. 클라인과 및 G. Lomow하여 자주 묻는 질문 (FAQ) 나는이에 액세스 할 수 없습니다 이 질문 대신 나는이 질문을합니다.)

+4

여기를 참조하십시오 : http://stackoverflow.com/questions/335369/finding-c-static-initialization-order-problems/335746#335746 –

+0

감사합니다, 그게 내가 ... – Tobias

+0

C++ FAQ 누락 된 점이다 Lite는 http://www.dietmar-kuehl.de/mirror/c로 옮겼습니다. ++ - faq/ – shargors

답변

4

전역 개체와 같은 정적 개체는 완전히 삭제됩니다 (생성 된 것으로 가정).

파괴 순서는 창조의 반대입니다.
따라서 개체가 파기하는 동안 다른 개체에 의존하는 경우 개체를 계속 사용할 수 있어야합니다. 이는 생성 순서가 올바르게 이루어짐으로써 파괴 명령을 강요 할 수 있기 때문에 상대적으로 간단합니다.

다음 링크는 singeltons에 관한 것입니다하지만, 비슷한 상황과 그 해결책에 대해 설명 : 우리는이 같은 문제를 해결할 수 라이트는 FAQ에 설명 된대로
Finding C++ static initialization order problems

게으른 초기화 된 전역의 일반적인 경우에 외삽을 :

namespace B 
{ 
    class B { ... }; 

    B& getInstance_Bglob; 
    { 
     static B instance_Bglob; 
     return instance_Bglob;; 
    } 

    B::~B() 
    { 
     A::getInstance_abc().doSomthing(); 
     // The object abc is accessed from the destructor. 
     // Potential problem. 
     // You must guarantee that abc is destroyed after this object. 
     // To gurantee this you must make sure it is constructed first. 
     // To do this just access the object from the constructor. 
    } 

    B::B() 
    { 
     A::getInstance_abc(); 
     // abc is now fully constructed. 
     // This means it was constructed before this object. 
     // This means it will be destroyed after this object. 
     // This means it is safe to use from the destructor. 
    } 
} 
namespace A 
{ 
    class A { ... }; 

    A& getInstance_abc() 
    { 
     static A instance_abc; 
     return instance_abc; 
    } 
} 
+0

C++ 0x의 수정 사항 중 하나는 함수 로컬 정적 변수의 결정적 파괴 순서입니다.따라서 C++ 03에서는 A가 B보다 먼저 생성 되더라도 A가 B보다 먼저 파괴된다는 보장이 없습니다. 주목할만한 예외는 A와 B가 같은 컴파일 단위에 정의 된 경우입니다. –

+1

@Caspin : 현재 표준 "ISO/IEC 14882"(http://openassist.googlecode.com/files/C%2B%2B%20Standard%20-%20ANSI%20ISO%20IEC%2014882%202003.pdf)에서 그것은 잘 정의되어있다. "3.6.3 종료"단락 참조 1 단락 : 고정 저장 기간 (블록 범위 또는 네임 스페이스 범위에서 선언 된)의 초기화 된 객체에 대한 소멸자 (12.4)가 main에서 반환되고 exit를 호출 한 결과로 호출됩니다 (18.3). 이러한 개체 은 생성자 완료 또는 동적 초기화 완료의 역순으로 삭제됩니다.

+0

당신이 옳은 것처럼 보입니다. 파괴 명령은 항상 역 구성 명령입니다. 나는 C++이 전체 프로그램이 아니라 컴파일 단위 내에서만 보장된다는 인상을 받았다. 나는 그 스펙을 더 자주 읽어야한다. C++ 0x에 대한 저의 코멘트는 새로운 표준으로 도입 된 새로운 멀티 스레드 파괴 명령에 대해 혼란 스러웠습니다. –

0

다른 객체의 정적 소멸자가 먼저 실행되는 한 괜찮습니다. "객체 A"이전에 다른 객체가 생성되도록함으로써이를 보장 할 수 있습니다. 두 객체가 같은 컴파일 유닛에서 선언되는 한, 소스에 나타나는 순서대로 초기화되고 반대 순서로 파괴됩니다.

컴파일 단위에서이 작업이 필요할 경우 운이 다되었습니다. 런타임시 동적으로 생성하고 정적으로 만들기보다 주 끝에서 종료하는 것이 더 좋습니다.

+0

OP는 특히 동일한 컴파일 단위에 전역 변수가 필요하지 않도록 패턴에 대한 링크를 인용합니다. 같은 기술을 사용하여 그는 정의 된 건설 질서와 정의 된 파괴 질서를 얻을 수 있으므로 운이 없다. –

0

약간의 해킹이지만 초기화의 순서를 추적하기 위해 정적 bool을 추가합니다. 그러면 소유자가 아니더라도 마지막으로 끝나는 객체가 정리를 수행합니다.

관련 문제