2010-01-29 8 views
3

나는 생성자와 소멸자에서 다른 클래스 (B)의 정적 변수 (STL 컨테이너)에 (정적 메서드를 통해 간접적으로) 액세스하는 클래스 (A)를가집니다.C++ 전역 객체의 소멸자 순서 제어

개체는 전역, 전역 상수, 다른 클래스의 정적 멤버 (자체적으로 전역 또는 정적 인스턴스가있을 수 있음) 또는 기본적으로 C++ 개체가 될 수있는 다른 위치에 저장 될 수 있습니다.

B 개체의 정적 멤버 앞에 A 개체가 생성되거나 B 개체의 정적 멤버가 소멸되면 어떤 시점에서 A 개체가 충돌합니다 (일반적으로 액세스 위반).

클래스 A의 모든 인스턴스 (누출 된 것들을 제외하고, "손실"되어 어떤 식 으로든 파괴되지 않을 것임)을 보장하는 방법이 있습니까? B의 정적 변수 이전에 파괴되고 파괴되었습니다.

특정 변수를 앞뒤로 생성/소멸시키는 몇 가지 솔루션을 보았습니다. 그러나 주어진 유형의 모든 인스턴스가 일반적인 경우는 아니므로이 방법에 접근하는 방법이 확실하지 않습니다.

답변

8

No. 이것은 static-initialization fiasco으로 알려져 있습니다. main에 들어가기 전에 객체가 생성되는 순서는 지정되지 않습니다. 유일한 보장은 그것이 일어나는 것입니다.

게으른 초기화가 가능합니다. 즉, 객체를 사용할 때까지 객체가 초기화되지 않습니다. 예를 들면 :

struct A { /* some data */ }; 
struct B { B(void){ /* get A's data */ } }; 

A& get_A(void) 
{ 
    static A instance; 
    return instance; 
} 

B& get_B(void) 
{ 
    static B instance; 
    return instance; 
} 

당신은 글로벌 인스턴스를 얻을 get_Aget_B를 사용합니다. B이 을 사용하는 부분은 get_A이어야하며 Bget_B이어야합니다. 귀하의 경우에는 get_B은 선택 사항입니다.

B를 처음 만들 때 어떻게됩니까? (전역 적 으로든 함수 내에서든) 생성자는 get_A을 호출하며 인 곳에서 A이 생성됩니다. 이것은 당신이 물건들이 만들어지는 순서를 제어하게합니다. 내가 생각

주 나는를 A를 반전 일반적으로 B.

+2

그는 초기화에 대한 것이 아니라 파괴에 대해 묻고 있습니다. –

+4

@Neil : 파괴 순서는 초기화 순서에 의해 결정됩니다. – GManNickG

+0

그래서 "정적 컨테이너 컨테이너"를 "정적 컨테이너 및 getContainer() {정적 컨테이너 컨테이너; 컨테이너 반환}"로 변경할 수 있으며 생성자에서 직접 또는 간접적으로 getContainer를 호출 한 후에 할당 취소됩니까? A의 인스턴스가 나중에 프로그램의 어느 시점에서 global shared_ptr에 저장되면 어떻게 될까요? –

1

, 그러한 방법. 그러나 해결 방법이 있습니다. 전역 포인터를 가지고 main/WinMain에서 초기화/파괴함으로써 전역 유효 범위와 전역 수명보다 약간 작은 개체를 얻을 수 있습니다. 또한 ref-counting 된 힙 오브젝트에서 마지막으로 destructed되도록 전역 상태를 배치합니다.

또한, 재 설계 :

1

"Modern C++ Design" 멋지게이 문제를 다루고 고려한다.

Google 도서 검색에는 섹션 6.5 (135 페이지) - link을 참조하십시오.

1

전역 공간에있는 객체에 포인터를 놓고 메인에 원하는 순서대로 새로 고치고 주 끝에서 원하는 순서대로 삭제하여이 작업을 깨끗하게 처리 할 수 ​​있습니다.

0

다른 사람들이 지적했듯이 Static initialization order fiasco 문제로 인해이 문제를 해결할 수있는 표준적이고 이식 가능한 방법은 없습니다.

그러나 약간의 디자인을 적용하여 문제를 해결할 수 있어야하므로 A와 B의 객체가 구성 될 때 (그리고 어떻게 조정되는지) 어느 정도 제어 할 수 있습니다. 창조적 인 패턴 Singleton과 같은 디자인 패턴을 살펴보십시오. 많은 경우 (대부분은 아닐지라도) anti-pattern으로 간주됩니다. 또한 좀 더 나은 싱글 톤으로 사용될 수있는 패턴 Monostate을보십시오. 이러한 패턴은 객체 생성 및 수명을 제어하는 ​​데 도움이되므로 사용하기 전에 상황이 올바르게 초기화됩니다.

일반적으로 전체를 피하는 것이 좋습니다. deglobalisation을 고수하는 것이 좋습니다.