boost::weak_ptr.lock() Crashes with a SIGSEGV S

2019-01-27 04:51发布

问题:

(EDIT) Environment:

plee@sos-build:/usr/local/include/boost$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 11.10
Release:        11.10
Codename:       oneiric

plee@sos-build:/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
plee@sos-build:/usr/local/include/boost$

plee@sos-build:/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"

I have been working on a server-side project. I use boost libraries, such as, boost::asio, boost::shared_ptr, and boost::weak_ptr.

The Boost documentation (http://www.boost.org/doc/libs/1_47_0/libs/smart_ptr/weak_ptr.htm#lock) says that the weak_ptr<T>.lock never throws:

lock

shared_ptr lock() const; Returns: expired()? shared_ptr(): shared_ptr(*this).

Throws: nothing.

However, in my application, it's even crashed:

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

I checked the line crashed in /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 }

The line 92 is assembly code. I really don't know what that means.

I always do the check if the returned boost::weakptr<RtmpConnection>.lock() (type of boost::shared_ptr<RtmpConnection> is empty before I used it.

So I googled, I saw this http://wiki.inkscape.org/wiki/index.php/Boost_shared_pointers

Weak pointers cannot be dereferenced for thread safety reasons. If some other thread destroyed the object after you checked the weak pointer for expiry but before you used it, you would get a crash

  1. So what should I do to deal with it, why does it crash (it seems boost::weakptr<RtmpConnection>.lock() should never crash)?
  2. Since my program is multithreaded. It's possible that after I get and check the returned value of boost::weakptr<RtmpConnection>.lock(), the RtmpConnection might be destroyed by other thread, does the Boost Library guarantee that it won't be destroyed, because the return type is boost::shared_ptr<RtmpConnection>?

回答1:

Most likely, you are violating one of the rules for proper use of smart pointers. Here are the most common smart pointer rules violations:

  1. An object must only be referenced through a single chain of smart pointers. Ideally, create a smart pointer with the object using make_shared and never use a raw pointer. But otherwise, create a smart pointer from a regular pointer only once.

  2. Only create a weak pointer from the object's strong pointer. (Or you can use shared_from_this if the object supports it.)

  3. An object must not be destroyed by calling delete while a smart pointer refers to it. Ideally, you would never call delete on an object that ever had any kind of smart pointer refer to it.

There are two other typical causes of problems like this. One is that you have a bug causing memory corruption such as array bounds overwrite, double free, access after free, and so on. You can check for a memory corruption bug with a tool like valgrind.

Lastly, you may have compiled your code incorrectly or compiled Boost incorrectly. For example, your platform might have compiler options that need to be enabled to compile thread-safe code. (You didn't mention your platform, so I can't give you specifics.)