2012-03-30 192 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

相关问题