【问题标题】:boost::shared_ptr's destructor block the only threadboost::shared_ptr 的析构函数阻塞了唯一的线程
【发布时间】:2012-06-08 16:27:28
【问题描述】:

我正在将一个 C++ 程序从 FreeBSD 移植到 RHEL。当我测试我的程序时,我发现调用 boost::shared_ptr::~shared_ptr() 时进程会挂起。

我使用gdb附加挂起进程,堆栈跟踪是:

(gdb) bt
#0  0x00e01430 in __kernel_vsyscall ()
#1  0x00bd8d96 in __pause_nocancel () from /lib/libpthread.so.0
#2  0x00bd30b2 in __pthread_mutex_lock_full () from /lib/libpthread.so.0
#3  0x04a60a26 in pthread_mutex_lock () from /lib/libc.so.6
#4  0x08069b61 in boost::detail::lightweight_mutex::scoped_lock::scoped_lock(boost::detail::lightweight_mutex&) ()
#5  0x080699d3 in boost::detail::sp_counted_base::release() ()
#6  0x08069999 in boost::detail::shared_count::~shared_count() ()
#7  0x08069952 in boost::shared_ptr<SS::Conf::SSConfNode>::~shared_ptr() ()
#8  0x00124fde in SS::Conf::SSConfManager::createConfFile(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) () from /home/y/lib/libSS_conf.so.1
#9  0x00125e0c in SS::Conf::SSConfManager::createAllConfFiles() () from /home/y/lib/libSS_conf.so.1
#10 0x0012946b in SS::Conf::SSConfManager::initFromDisk(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) () from /home/y/lib/libSS_conf.so.1
#11 0x00129c3b in SS::Conf::SSConfManager::configure(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) () from /home/y/lib/libSS_conf.so.1
#12 0x00156d0c in SS::Init::configure() () from /home/y/lib/libSS_init.so.1
#13 0x0805ac63 in SS::Main::init() ()
#14 0x0807117e in main ()

而我的进程只包含一个线程:

(gdb) info thread
* 1 Thread 0xf77a8a40 (LWP 16724)  0x00c54430 in __kernel_vsyscall ()

当我在头文件中undef BOOST_HAS_THREADS 并重建程序时,一切顺利。

boost 版本是 1.32,我在 RHEL4.8 上使用 gcc 3.4.6-11。

【问题讨论】:

  • Boost 1.32 已经很老了。尝试更新版本也许是个好主意?
  • 错误在文件detect_missing_code.cc的第574行。在一个更严重的节点上:请发布简短、自包含和正确的示例,否则人们只能下定决心猜测。见sscce.org
  • 源代码乱七八糟,我稍后会尝试添加一些自包含的代码。

标签: c++ boost locking shared-ptr


【解决方案1】:

我不确定问题是什么,但这可能是1.32 documentation 的相关部分:

shared_ptr 使用Boost.Config 来检测实现是否支持线程。如果您的程序是单线程的,但您的平台被Boost.Config 自动检测为支持多线程,#define BOOST_DISABLE_THREADS 以消除线程安全开销。

因此,考虑使用#define BOOST_DISABLE_THREADS 而不是取消定义BOOST_HAS_THREADS

这是1.33 and beyond documentation

从 Boost 1.33.0 版开始,shared_ptr 在以下平台上使用无锁实现:

  • x86 或 x86-64 上的 GNU GCC;
  • IA64 上的 GNU GCC;
  • PowerPC 上的 Metrowerks CodeWarrior;
  • PowerPC 上的 GNU GCC;
  • 窗户。

如果你的程序是单线程的并且没有链接到任何可能在其默认配置中使用 shared_ptr 的库,你可以在项目范围内#defineBOOST_SP_DISABLE_THREADS 切换到普通的非原子引用计数更新。

(在某些(但不是全部)翻译单元中定义 BOOST_SP_DISABLE_THREADS 在技术上违反了单一定义规则和未定义的行为。尽管如此,实现尝试尽最大努力适应使用非原子更新的请求那些翻译单元。但不能保证。)

您可以定义宏 BOOST_SP_USE_PTHREADS 以关闭特定于平台的无锁实现并回退到基于通用 pthread_mutex_t 的代码。

【讨论】:

    【解决方案2】:

    终于找到原因了。 我的主程序使用 boost 1.32 构建,但我的 .so 文件之一是使用 boost 1.38 构建的。运行我的程序并导致此问题时,有 2 个 shared_ptr 实现。在我用 boost 1.32 重建我的 so 文件后,程序运行良好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-12
      • 2011-05-29
      • 1970-01-01
      • 1970-01-01
      • 2015-07-06
      • 2014-05-26
      • 1970-01-01
      相关资源
      最近更新 更多