2013-06-27 3 views
1

클래스와 같은 부스트 ​​신호를 작성하려고합니다 (C++을 배우기위한 연습으로). 그리고 내가 enable_shared_from_this을 사용할 때, 나는 항상 소멸자에서 충돌을 발견했습니다. 다음은 코드입니다 (vs2012 업데이트 2를 사용하고 있습니다) :std :: enable_shared_from_this를 사용할 때 소멸자에서 크래시가 발생했습니다.

이 모든 의견이 있으십니까? 이 문제는 signal_connection::disconnect의 줄 (auto this_ = shared_from_this();)의 주석을 제거 할 때 모든 것이 정상적으로 작동하므로 shared_from_this()이 발생해야합니다.

shared_from_this()을 호출하기 전에 적어도 하나의 유효한 shared_ptr이 있어야한다는 것을 알고 있습니다. 내 코드가이를 만족해야합니다.

코드는 :

#include <memory> 
    #include <map> 

    class slot_manager; 

    class signal_connection: public std::enable_shared_from_this<signal_connection> 
    { 
    public: 
     signal_connection(slot_manager* manager) 
      :manager_(manager) 
     {} 
    public: 
     void disconnect() ; 
    private: 
     slot_manager* manager_; 
    }; 

    class slot_manager 
    { 
    public: 
     typedef std::shared_ptr<signal_connection> connection_type; 
     typedef std::map<connection_type, int> map_type; 
     typedef map_type::value_type map_value_type; 
    public: 
     void connect(int slot) 
     { 
      std::shared_ptr<signal_connection> c(new signal_connection(this)); 
      slots_.insert(map_value_type(c, slot)); 
     } 
     ~slot_manager() 
     { 
      auto iter = slots_.begin(); 
      map_type::iterator iter2 = slots_.end(); 
      while (iter != slots_.end()) 
      { 
       iter2 = iter++; 
       iter2->first->disconnect(); 
      } 
     } 
     void disconnect(std::shared_ptr<signal_connection> connection) 
     { 
      auto c = slots_.find(connection); 
      if (c != slots_.end()) 
      { 
       slots_.erase(c); 
      } 
     } 
    protected: 
     map_type slots_; 
    }; 

    void signal_connection::disconnect() 
    { 
     if (manager_ != nullptr) 
     { 
      //auto this_ = shared_from_this(); 
      manager_->disconnect(shared_from_this()); 
      manager_ = nullptr; 
     } 
    } 

    int _tmain(int argc, _TCHAR* argv[]) 
    { 
     slot_manager x; 
     x.connect(1); 
    return 0; 
    } 
+2

@KerrekSB : 당신은 공손한 프로그래머가 공개적으로 알몸으로 가지 않는다는 것을 의미합니까? 포장 된 것만? :) – Xeo

+0

나는'make_shared'를'new'로 선호합니다. 그러나 그것은 어떤 문제의 원인이 아닙니다. – aschepler

+0

valgrind는 Mac OS에서이 문제를 즉시 발견했습니다. 프로그램이 중단되지는 않았지만. 그것을 사용하십시오, 그것을 좋아하십시오 : valgrind. –

답변

6

문제는 당신이 관리자의 분리에 대한 호출에 의해 즉, 다음 액세스 위반이 발생 nullptr과의 매니저를 설정하기 전에 signal_connection이 disconnect()에 detroyed된다는 점이다. 이는 관리자가 연결에 shared_ptr 만 보유하고 있으므로 erase()입니다. 객체 자체가 살아 있지 않습니다. 물론, 해당 줄을 주석 처리하지 않은 한. this_은 문제를 회피하기에 충분히 오래 살아 있습니다.

+0

대단히 감사합니다. 내 가정은 signal_connection이 소멸자 'iter2-> first-> disconnect();'에서이 문장 다음에 파기되어야한다는 것이다. 다시 감사합니다! –

관련 문제