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::asio, boost::shared_ptr, а такжеboost::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 lock () const; Возвращает: истек ()? shared_ptr (): shared_ptr (* это).

Броски: ничего.

Тем не менее, в моем приложении, он даже разбился:

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

Слабые указатели не могут быть разыменованы по соображениям безопасности потоков. Если какой-то другой поток уничтожит объект после того, как вы проверили слабый указатель на истечение срока действия, но перед тем, как использовать его, вы получите сбой

Итак, что я должен сделать, чтобы справиться с этим, почему он падает (кажется,boost::weakptr<RtmpConnection>.lock() никогда не должен разбиться)?Так как моя программа многопоточная. Возможно, что после того, как я получу и проверю возвращенное значениеboost::weakptr<RtmpConnection>.lock(),RtmpConnection может быть уничтожен другим потоком, гарантирует ли Boost Library, что он не будет уничтожен, потому что возвращаемый типboost::shared_ptr<RtmpConnection>?
 Peter Lee30 мар. 2012 г., 20:16
@ Давид, ноlock() Сам метод не должен сбой, верно? Если он уже уничтожен, он должен вернуть пустоеshared_ptr<>, правильно? Кстати, что можно включить, чтобы компилировать потокобезопасный код в Boost?
 David Schwartz30 мар. 2012 г., 20:21
Метод блокировки завершится сбоем, если объект былнеправильно уничтожены. Например, если он был уничтожен, когда на него все еще ссылается сильный указатель, или если на него ссылались более чем одна цепочка интеллектуальных указателей. В Boost нет возможности скомпилировать потокобезопасный код - это будет вариант в компиляторе для любой используемой вами платформы.
 David Schwartz30 мар. 2012 г., 20:02
Скорее всего, сам слабый указатель был освобожден, слабый указатель был поврежден из-за перезаписи его памяти, объект был удален, хотя сильный указатель все еще указывал на него, или у вас есть несколько цепочек умных указателей, которые ссылаются на один и тот же объект. (Также возможно, что Boost был скомпилирован неправильно. Например, ваша платформа может иметь опции, которые необходимо включить для компиляции поточно-ориентированного кода.)

Ответы на вопрос(1)

вы нарушаете одно из правил правильного использования умных указателей. Вот наиболее распространенные нарушения правил умного указателя:

На объект нужно ссылаться только через одну цепочку умных указателей. В идеале, создать умный указатель с помощью объектаmake_shared и никогда не используйте необработанный указатель. Но в противном случае создайте умный указатель из обычного указателя только один раз.

Создайте только слабый указатель из сильного указателя объекта. (Или вы можете использоватьshared_from_this если объект поддерживает это.)

Объект не должен быть уничтожен путем вызоваdelete в то время как умный указатель ссылается на это. В идеале вы бы никогда не позвонилиdelete на объекте, который когда-либо имел какой-либо умный указатель, обращайтесь к нему.

Есть две другие типичные причины таких проблем. Во-первых, у вас есть ошибка, приводящая к повреждению памяти, например, перезапись границ массива, двойное освобождение, доступ после освобождения и так далее. Вы можете проверить наличие ошибки повреждения памяти с помощью такого инструмента, какvalgrind.

Наконец, вы, возможно, неправильно скомпилировали свой код или неправильно скомпилировали Boost. Например, ваша платформа может иметь параметры компилятора, которые необходимо включить для компиляции поточно-ориентированного кода. (Вы не упомянули свою платформу, поэтому я не могу дать вам подробности.)

 v.oddou04 авг. 2014 г., 03:23
Вы уверены, что valgrind работает действительно параллельно? valgrind может сериализовать выполнение через упреждающий планировщик, встроенный в его виртуальную машину c ++.
 Peter Lee30 мар. 2012 г., 21:11
Я очень тщательно проверил правила, которые мог нарушить, насколько мне известно, я не нарушал ни одно из упомянутых вами правил. Так что я сейчас делаюvalgrind проверить. Я немного обеспокоен тем, что valgrind значительно замедляет работу приложения, и эта ошибка может быть воспроизведена (также иногда) при нагрузочном тестировании клиентского соединения 50 или 100.

Ваш ответ на вопрос