天天看點

C++多線程Linux多線程服務端程式設計使用muduo C++網絡庫:用shared_ptr解決并發程式設計中的記憶體問題

C++裡可能出現的記憶體問題:

  1. 緩沖區溢出 : 用 vector 或 string 管理緩沖區,并通過成員函數而不是裸指針修改緩沖區
  2. 空懸指針/野指針:用 shar_ptr / weak_ptr
  3. 重複釋放:用 scoped_ptr,隻在對象析構的時候釋放一次
  4. 記憶體洩漏:用 scoped_ptr,對象析構的時候自動釋放記憶體
  5. 不配對的new[]/delete:把 new[] 通通換為 vector / scoped_array
  6. 記憶體碎片
shared_ptr用法小結
  1. 意外延長對象的生命周期

    使用 bind 綁定了一個 share_ptr指向的一個函數或成員函數

  2. 線程安全問題:
  • 不同的shared_ptr即使綁定了相同的對象也是線程安全的
  • 對同一shared_ptr任何操作線程不安全
  1. 傳遞shared_ptr對象的技巧

    shared_ptr< T >p;

  • 若直接傳遞 f ( p ) ,由于線程安全問題,傳遞之前要加鎖,但由于是同步調用過程,加鎖後要等調用函數執行完再解鎖,這樣的效率太低
  • 可以先加鎖對 shared_ptr 拷貝後解鎖,傳遞拷貝後的值,利用const &接收,減少一次拷貝(因為shared_ptr的拷貝需要改變引用計數,導緻拷貝的代價要比普通指針高,是以盡量不拷貝)
  1. 析構動作在建立時捕獲

    對象的析構是同步的,當最後一個指向 x 的 shared_ptr 離開其作用域的時候,x 會同時在同一個線程析構,這個線程不一定是對象誕生的線程。如果對象的析構比較耗時,那麼可能會拖慢關鍵線程的速度。我們可以用一個單獨的線程專門做析構,通過一個BlockingQueue< shared_ptr >把對象的析構都轉移到專用線程,進而解放關鍵線程

  2. 注意避免循環引用

    通常的做法是 owner 持有指向 child 的 shared_ptr,child 持有指向 owner 的 weak_ptr

  3. enable_shared_from_this

    類 T 通過繼承 enable_shared_from_this< T >,可以通過 shared_from_this() 傳回shared_ptr 共享目前執行個體的所有權( 為了使用shared_from_this() ,object 不能是stack object ,必須是 heap object 且由shared_ptr 管理其生命期 )