2012-03-30 59 views
1

(編輯)環境:的boost :: weak_ptr的<T> .lock()崩潰了SIGSEGV段錯誤

[email protected]:/usr/local/include/boost$ lsb_release -a 
No LSB modules are available. 
Distributor ID: Ubuntu 
Description: Ubuntu 11.10 
Release:  11.10 
Codename:  oneiric 

[email protected]:/usr/local/include/boost$ uname -a 
Linux sos-build 3.0.0-12-generiC#20-Ubuntu SMP Fri Oct 7 14:56:25 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux 
[email protected]:/usr/local/include/boost$ 

[email protected]:/usr/local/include/boost$ cat version.hpp 
// BOOST_LIB_VERSION must be defined to be the same as BOOST_VERSION 
#define BOOST_LIB_VERSION "1_47" 

我一直在服務器端項目。我使用boost庫,如boost::asioboost::shared_ptrboost::weak_ptr

Boost文檔(http://www.boost.org/doc/libs/1_47_0/libs/smart_ptr/weak_ptr.htm#lock)說,weak_ptr<T>.lock從不拋出:

shared_ptr的鎖()const的;返回:expired()? shared_ptr(): shared_ptr(* this)。

拋出:無。

然而,在我的應用程序,它甚至崩潰:

Program received signal SIGSEGV, Segmentation fault. 
[Switching to Thread 0x7fffeffff700 (LWP 5102)] 
0x000000000066fe08 in boost::detail::atomic_conditional_increment (pw=0x800000000007) 
    at /usr/local/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp:92 
92  ); 
(gdb) 
(gdb) bt 
#0 0x000000000066fe08 in boost::detail::atomic_conditional_increment (pw=0x800000000007) 
    at /usr/local/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp:92 
#1 0x000000000066fe5c in boost::detail::sp_counted_base::add_ref_lock (this=0x7fffffffffff) 
    at /usr/local/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp:138 
#2 0x000000000068009b in boost::detail::shared_count::shared_count (this=0x7fffefffe658, r=...) 
    at /usr/local/include/boost/smart_ptr/detail/shared_count.hpp:518 
#3 0x0000000000691599 in boost::shared_ptr<RtmpConnection>::shared_ptr<RtmpConnection> (
    this=0x7fffefffe650, r=...) at /usr/local/include/boost/smart_ptr/shared_ptr.hpp:216 
#4 0x000000000068db48 in boost::weak_ptr<RtmpConnection>::lock (this=0x7fffe0e87e68) 
    at /usr/local/include/boost/smart_ptr/weak_ptr.hpp:157 

我檢查了線/usr/local/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp

69 inline int atomic_conditional_increment(int * pw) 
70 { 
71  // int rv = *pw; 
72  // if(rv != 0) ++*pw; 
73  // return rv; 
74 
75  int rv, tmp; 
76 
77  __asm__ 
78  (
79   "movl %0, %%eax\n\t" 
80   "0:\n\t" 
81   "test %%eax, %%eax\n\t" 
82   "je 1f\n\t" 
83   "movl %%eax, %2\n\t" 
84   "incl %2\n\t" 
85   "lock\n\t" 
86   "cmpxchgl %2, %0\n\t" 
87   "jne 0b\n\t" 
88   "1:": 
89   "=m"(*pw), "=&a"(rv), "=&r"(tmp): // outputs (%0, %1, %2) 
90   "m"(*pw): // input (%3) 
91   "cc" // clobbers 
92 ); 
93 
94  return rv; 
95 } 

線92彙編代碼墜毀。我真的不知道這意味着什麼。

我總是做檢查,如果返回的boost::weakptr<RtmpConnection>.lock()(類型boost::shared_ptr<RtmpConnection>是空的之前,我用它。

所以我一派,我看到這個http://wiki.inkscape.org/wiki/index.php/Boost_shared_pointers

弱指針不能被解除引用線程安全的原因。如果 其他線程破壞了對象,你檢查的薄弱 指針期滿後,但你使用它之前,你會得到一個崩潰

  1. 那麼我該怎麼處理它,爲什麼會崩潰(看來boost::weakptr<RtmpConnection>.lock()應該永遠不會崩潰)?
  2. 由於我的程序是多線程的。有可能在我得到並檢查返回值boost::weakptr<RtmpConnection>.lock()後,RtmpConnection可能會被其他線程銷燬,Boost庫是否保證它不會被銷燬,因爲返回類型是boost::shared_ptr<RtmpConnection>
+0

最有可能的是,弱指針本身被釋放,弱指針被覆蓋內存破壞,對象被刪除,即使強指針仍然指向它,或者您有多個指向同一對象的智能指針鏈。 (Boost也可能編譯不正確,例如,你的平臺可能有需要啓用的選項來編譯線程安全的代碼。) – 2012-03-30 18:02:35

+0

@David,但'lock()'方法本身不應該崩潰,對吧?如果它已經被銷燬,它應該返回一個空的'shared_ptr <>',對吧?順便說一下,有什麼選項可以在Boost中編譯線程安全的代碼? – 2012-03-30 18:16:50

+0

如果對象被*不當*損壞,鎖定方法會崩潰。例如,如果它在一個強指針仍然引用它的時候被銷燬,或者它通過多個智能指針鏈被引用。沒有選項可以在Boost中編譯線程安全的代碼 - 這是編譯器中用於任何平臺的選項。 – 2012-03-30 18:21:16

回答

1

很可能,您違反了正確使用智能指針的規則之一。以下是最常見的智能指針規則違規:

  1. 一個對象只能通過一個智能指針鏈來引用。理想情況下,使用make_shared創建一個智能指針,並且不要使用原始指針。但除此之外,只需從常規指針創建一個智能指針一次。

  2. 只能從對象的強指針創建弱指針。 (或者,如果對象支持,則可以使用shared_from_this。)

  3. 當智能指針指向它時,不得通過調用delete銷燬對象。理想情況下,您永遠不會在有任何智能指針參考的對象上調用delete

還有其他兩個典型的原因,像這樣的問題。一個是你有一個導致內存損壞的bug,例如數組邊界覆蓋,雙倍空閒,空閒後訪問等等。您可以使用類似valgrind這樣的工具來檢查內存損壞問題。

最後,您可能錯誤地編譯了您的代碼或編譯了錯誤的Boost。例如,您的平臺可能具有需要啓用編譯線程安全代碼的編譯器選項。 (你沒有提到你的平臺,所以我不能提供你的具體情況。)

+0

我非常認真地檢查了我可能違反的規則,據我所知,我沒有違反任何你提到的規則。所以我現在正在做一個'valgrind'檢查。我擔心valgrind會顯着降低應用程序的運行速度,並且可能會在50或100個客戶端連接負載測試中重現(有時也會)此錯誤。 – 2012-03-30 19:11:18

+0

你確定valgrind是以一種非常平行的方式執行嗎? valgrind可以通過其C++虛擬機內部的搶先式調度器序列化執行。 – 2014-08-04 01:23:10