2013-06-27 45 views
1

我想寫一個像類一樣的boost信號(作爲練習學習C++)。我發現當我使用enable_shared_from_this時,我總是在析構函數中崩潰。這裏是代碼(我正在使用vs2012更新2):使用std :: enable_shared_from_this時析構函數崩潰

對此的評論如何?這個問題應該引起shared_from_this(),因爲當我取消註釋signal_connection::disconnect中的行(auto 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

儘管程序沒有崩潰,但在Mac OS上,valgrind馬上發現了這個問題。使用它,愛它:valgrind。 –

回答

6

的問題是,signal_connection在disconnect() detroyed您通過電話經理的斷開設置其經理nullptr,然後會導致訪問衝突,即前。這是因爲經理持有唯一的shared_ptr來連接,而你erase()那。該對象不保持自己的活力。當然,除非你取消註釋。 this_只是活得夠長,以避免這個問題。

+0

非常感謝。我的假設是signal_connection應該在析構函數'iter2-> first-> disconnect();'之後被銷燬,根據您的評論這是錯誤的。再次感謝你! –

相關問題