2011-09-19 4 views
4

내 프로그램의 많은 개체에서 사용되는 전역 단독 파일이 있습니다. 이것은 프로그램이 종료 될 때 크래시를 일으키고 있습니다. 싱글 톤 자체가 프로그램 끝으로 파괴 된 후 일부 객체의 소멸자에서 사용됩니다. 포인터가 'delete'를 호출했는지 알 수있는 이식 가능한 방법이 있습니까? 필자의 경우, delete는 (void *) (- 1) 포인터의 값을 변경하는 것처럼 보이지만, 이식성이 있는지는 알 수 없다.C++ 포인터가 파괴되었는지 알 수 있습니까?

+6

아니요, 그렇지 않아야합니다. "singleton antipattern"과 "static initialization hell"을 찾으십시오. –

+0

'delete'는 포인터의 값을 변경해서는 안됩니다. –

+0

아마도 디버그 빌드에 있었을 것입니다. –

답변

6

아니요, C++ 포인터가 가리키는 개체가 소멸되었는지 여부를 알 수 없습니다.

스마트 포인터를 사용하면 자동으로 처리 할 수 ​​있습니다.

+0

이것은 파괴 명령에 도움이되지 않습니다. 그래도 싱글 톤. –

+0

@ André Caron : 사실,하지만 언어 변경 사항을 제외하면 아무 도움이되지 않습니다. –

+2

디자인 상 문제가있는 것처럼 보입니다. –

0

불가능하고 정의되지 않은 영역이라고 생각했을 것입니다.

다른 모든 것이 정리 된 후에야 싱글 톤을 삭제하지 않는 것이 가장 좋습니다. 그렇지 않으면 인스턴스를 삭제 한 후 포인터를 NULL로 설정 한 다음이를 확인할 수 있습니다. 그것은 리팩토링이 순서대로되어있는 것처럼 들립니다.

0

말한대로, 당신은 할 수 없습니다. 이를 추적 할 수있는 여러 기술이 있지만 플랫폼에 따라 다릅니다.

우선, 실제 문제는 무엇입니까? 당신은 싱글 톤을 가지고 있는데, 그것은 파괴되었을 때 다른 객체에 의해 사용됩니다. 만약 당신의 싱글 톤이 C Runtime에 의해 파괴된다면, 다른 오브젝트들을 파괴 할 수 있을까요?

+0

C 런타임은이 객체 바로 뒤에있는 다른 객체도 파괴합니다. –

+0

그래서 여기에 디자인 문제가 있습니다. C 런타임에서 보장되는 특정 소멸자 순서가 없습니다. 싱글 톤이 파괴되었는지 확인하는 것은 적절한 해법이 아니라 해킹입니다. 싱글 톤의 방법은 무엇을합니까? –

0

싱글 톤을 삭제하는 것을 결정하는 가장 쉬운 방법은 싱글 톤의 소멸자를 비공개로 만드는 것입니다. 그런 다음 삭제하려고하는 위치에 컴파일 오류가 발생해야합니다.

1

간단한 답 : 포인터를 사용하지 마십시오

  • .
  • 고전적인 Myers 싱글 톤을 사용하십시오.

그렇다면 개체가 개체 뒤에 인스턴스화되었는지 확인한 후 개체를 보장해야합니다. 객체가 생성되기 전에 객체가 인스턴스화되기 전에 인스턴스화되었는지 확인하십시오.

엄지 손가락의 규칙 : 소멸자에서 싱글 톤을 사용하려는 경우. 먼저 생성자에서 사용하십시오.

class A 
{ 
    A(); 
    A(A const&); 
    A& operator=(A const&); 
    public: 
     static A& getInstance() // return reference. 
     { 
      static A instance; // Created on first use. 
           // So lazily created when expensive. 

      return instance; // Guaranteed to be destroyed in reverse order of 
           // creation In comparison to other static storage 
           // duration objects. Thus if it is created before 
           // your object It is guaranteed to be correctly 
           // destroyed after your object. 

           // If you want to guarantee it is created before your 
           // object just call A::getInstance() in your constructor 
           // the static member 'instance' will only be created 
           // once and returning a reference is not expensive. 
     } 
     // If you are creating this from the constructor of a global 
     // Then threading becomes a non issues as threads are not started before main 
     // If you are using pthreads or Windows threads you potentially can start them 
     // but it is undefined if they will work so again not your issue. 
}; 
0

이 코드는 정적 인스턴스의 수명을 추적합니다. 당신이 힙을 할당하면 똑같이 잘 작동합니다. 물론 인스턴스가 아직 생성되지 않은 경우에도 instance()에 대한 첫 번째 호출이 수행됩니다. 그러나 전역 정적 소멸자의 복잡한 메시가있는 경우이 인스턴스를 사용하여 인스턴스가 소멸되었는지 여부를 확인할 수 있어야합니다.

class Thing 
{ 
public: 
    enum State { preConstruction, constructed, destructed }; 
    static const State& singletonState() { return state_;} 
    static Thing& instance() 
    { 
     static Thing instance; 
     return instance; 
    } 
private: 
    Thing() 
    { 
     state_ = constructed; 
    } 
    ~Thing() 
    { 
     state_ = destructed; 
    } 
    static State state_; 
}; 

Thing::State Thing::state_ = Thing::preConstruction; 
관련 문제