boost::shared_ptr的析构函数阻止了唯一的线程

boost::shared_ptr's destructor block the only thread

本文关键字:唯一 线程 析构函数 ptr boost shared      更新时间:2023-10-16

我正在将一个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 ()

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

提升版本是 1.32,我在 RHEL3.4.6-11 上使用 gcc 4.8。

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

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

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

这是 1.33 及更高版本的文档:

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

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

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

在某些(但不是全部)翻译单元中定义BOOST_SP_DISABLE_THREADS在技术上违反了一个定义规则和未定义的行为。尽管如此,实现会尽力满足在这些翻译单元中使用非原子更新的请求。不过,不能保证。

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

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