2013-02-24 4 views
0

Visual C++ 런타임에서 프로그램이 종료 될 때 개체가 파괴되는 것과 관련된 다소 성가신 문제가 발생했습니다.Visual C++ 런타임 개체 파괴 순서

나는 특정 주에 대한 참조가 유효한지 확인하는 데 사용되는 클래스가 있습니다. 알 수없는 시간 동안 상태를 저장해야하며이 시간 동안 상태가 파괴 될 수 있으며 shared_ptr을 사용할 수 없습니다. 그래서 MyClass의 각 인스턴스는 생성자 refed_list에 자신을 추가하고 소멸자에서 자신을 제거

class MyClass 
{ 
private: 
    static std::list<MyClass*> make_list(); 
    static std::list<MyClass*> refed_list;   
    static void StateClosed(B* state); 

public: 
    B* state; 
    MyClass(B* state); 
    virtual ~MyClass(); 

    bool still_valid() const; 
}; 

를 사용합니다. 캡슐화 상태가 닫히면 MyClass이 알리고 캡슐화 인스턴스에 대해 refed_list을 확인하고 해당 포인터를 무효화합니다. 이것은 실제로 관련이 없습니다. 중요한 것은 static list을 사용하고 생성자/소멸자에서이 목록에 액세스한다는 것입니다. MyClass이 정의 된 파일에서 refed_list을 초기화합니다.

문제가 .. 내 프로그램이 닫히면 런타임에 refed_list이 정리되고 그 후에는 소멸자를 호출하여 MyClass의 인스턴스를 정리합니다. 그런 다음 이미 정리 된 refed_list에 액세스하려고합니다. 결과적으로 내 반복자가 올바르지 않으며 결과가 정의되지 않은 디버그 어설 션 오류가 발생합니다.

이 문제를 해결할 방법이 있습니까? 난 다른 컴파일 단위의 어떤 주문 개체가 파괴 될지 지정할 수는 없지만 refed_list이 유효한지 확인하는 방법이 있습니까? 지금은 refed_list.size() == 0인지 확인하고 작동하는 것처럼 보이지만이 동작은 정의되지 않았습니다 (제 생각에는?). 나는이 생각하지 않습니다

+1

싱글 톤 수명 문제와 비슷합니다. 나는 Scott Meyers 또는 Andrei Alexandrescu가 3 가지 또는 다른 방식으로 그들을 관리하는 것에 관해 썼다고 생각한다. 피닉스 싱글 톤이 당신의 골목을 넘을 수도 있습니다. –

+0

그리고 이것이 내 팀에서 전역 클래스 인스턴스를 허용하지 않는 많은 이유 중 하나입니다. 프로그램 종료 중 오브젝트 파기의 순서는 비 결정적이거나 올바르게되기가 어렵 기 때문에. 어쨌든 WinMain/main 반환 전에 응용 프로그램 정리 기능을 실행할 수 있습니까?아니면 더 나은 아직, 그 소멸자가 뭔가 중요한 임무를 수행하지 않는 한, 왜 모든 개체가 응용 프로그램 종료시 유출하지 않겠습니까? – selbie

+0

@selbie 좋은 생각이라고 생각하기 시작했습니다. 내가 이것을하고있는 이유는 사용되기 전에 무효화 될 수있는 객체를 저장해야하기 때문에'shared_ptr'을 사용할 수 없기 때문에 객체가 유효한지 여부를 알려주는 것이 필요합니다. 따라서 개체를 추적해야하므로 정적 목록이 있습니다. 하지만 그래, 내가 몇 가지를 다시 작성하면 수동으로 닫아서 내 문제를 해결할 수있다. 프로세스로 연결하면 때때로 어려운 일이 일어난다. – user1520427

답변

2

항상 refed_list을 시작할 때 초기화되는 포인터로 만들 수 있습니다. 그런 식으로는 결코 정화되지 않을 것입니다. (그리고 프로세스가 종료 될 때 OS가 사용하는 메모리는 복구 될 것입니다.)

심층적 인 디자인 문제를 해결하기 위해 해킹 소리가 들린다면 아마 그럴 것입니다. :)

+0

디자인이 좋지 않습니다. 런타임이 내 전역 변수를 정리하기 전에 정리할 수 있도록 소멸자를 모방하는 메소드를 작성해야했습니다. – user1520427

0

사실이다 :

내 프로그램은 런타임이 어떤 점에서 refed_list를 정리 닫을 때,이 후에는 자신의 소멸자를 호출, MyClass에의 인스턴스를 정리합니다.

런타임은 목록이기 때문에 확실하게 목록을 지우지 만 목록에있는 객체는 포인터이기 때문에 정리하지 않습니다. 이를 수행하는 유일한 방법은 shared_ptr과 같은 스마트 포인터 클래스를 사용하는 것입니다. 그래도, 만약 당신이 그렇게했다면, 객체는 파괴되는 동안 목록에 접근하려고 시도 할 것입니다. 이것은 정의되지 않은 동작이지만 확실하게 불안정한 것 같습니다.

아마도 개체가 저장되어있는 목록을 참조 할 필요가 없도록 만들거나 최소한 전에이라는 목록이 삭제되기 전에 다시 디자인해야합니다. ~ 목록도 호출됩니다).

+0

내가 저장 한 포인터의 메모리가 해제된다는 것을 의미하지는 않는다. 나중에 MyClass를 상속받은 객체가 파괴되어 나중에 'MyClass' 소멸자가 실행된다. 지금 파괴 된 목록에 액세스하십시오. 하지만 예, 재 설계가 순서대로 진행되는 것 같습니다. – user1520427