我有一个线程 A 分配内存并将其分配给共享指针。然后这个线程产生 3 个其他线程 X、Y 和 Z,并将共享指针的副本传递给每个线程。当 X、Y 和 Z 超出范围时,内存被释放。但是是否有可能 2 个线程 X、Y 在完全相同的时间点超出范围,并且引用计数存在竞争条件,因此它不会减少 2,而是只减少一次。所以,现在更新的引用计数下降到 0,所以存在内存泄漏。请注意,X、Y 和 Z 只是读取内存。不写入或重置共享指针。长话短说,引用计数是否存在竞争条件,这会导致内存泄漏吗?
5 回答
boost::shared_ptr
使用锁(或无锁原子访问)来确保引用计数被原子更新(即使这在文档页面中并不清楚)。如果您正在编写单线程代码,则可以通过定义宏来配置锁的使用BOOST_SP_DISABLE_THREADS
。
请注意,http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/shared_ptr.htm#ThreadSafety中讨论来自不同线程的多次写入问题的文档示例正在讨论那些作用于相同shared_ptr
实例的线程(示例中的shared_ptr
对象可能是全局对象),而不是shared_ptr
指向同一对象的不同副本,这是shared_ptr
's. 您在问题中给出的示例(作用于指向共享对象的副本)是线程安全的。
不,根据文档,这些问题不会发生:
不同
shared_ptr
的实例可以由多个线程同时“写入”(使用可变操作,例如 operator= 或 reset 访问)(即使这些实例是副本,并且在下面共享相同的引用计数。)
其他几个人已经提供了文档的链接,说明这是安全的。
boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
对于绝对无可辩驳的证据,请参阅 Boost Smartptr 实际上是如何在(或您的平台的相应文件)中从头开始实现自己的互斥锁的。
文档说:
不同的 shared_ptr 实例可以被多个线程同时“写入”(使用诸如 operator= 或 reset 之类的可变操作访问)(即使这些实例是副本,并且在下面共享相同的引用计数。)
因此,如果没有一个线程访问其他线程的指针对象,那应该没问题。请查看文档中的示例,看看哪一个与您的情况相关。
最好的办法是升级到 TR1 或 C++0x shared_ptr,而不是 Boost 品种。我相信那些必须是线程安全的是标准化的。