Shared_ptr 在创建增强线程时从未解除分配

Shared_ptr never deallocated when boost threads created

所以我这里有一个奇怪的情况。我有以下代码:

int main()
{
    std::shared_ptr<MyClassA> classA = std::shared_ptr<MyClassA>(new MyClassA);
    std::shared_ptr<MyClassB> classB = std::shared_ptr<MyClassB>(new MyClassB(classA));

    boost::thread_group threadGroup;

    // This thread is essentially an infinite loop waiting for data on a socket
    threadGroup.create_thread( boost::bind(&MyClassB::method1, classB) );

    ...do stuff

    return 0;
}

MyClassB 打开了几个资源,这些资源在程序退出时不会被释放。但是,如果我删除对 create_thread 的调用,资源将被释放。我在 MyClassB 的析构函数中放置了一个打印输出,并验证如果创建该线程它不会被调用。

有人知道这里发生了什么吗?

由于您将指向 class B 的共享指针传递给您的线程,您的线程现在共享该实例。在此线程自然退出之前,不会释放此资源。

根据文档 boost::thread_group 析构函数销毁所有 onwed 线程。 boost::thread 析构函数顺序:

  • if defined BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE: If *this has an associated thread of execution, calls detach(), DEPRECATED
  • BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable calls to std::terminate. Destroys *this.

因此您需要显式加入线程。您可以通过在程序结束时调用 boost::thread_group::join_all() 来做到这一点。

// This thread is essentially an infinite loop waiting for data on a socket

这条评论很有说服力。您的线程可能 运行 永远,远远超过程序的结尾。如果是这种情况,您需要在退出 main 之前分离线程,并且您应该不会看到析构函数被调用。该线程仍然存在并共享该对象的所有权。

...do stuff

如果 ...do stuff 不涉及分离或加入该线程,则您正在调用 Boost 中的未定义行为。如果您从使用 boost::thread 切换到使用 std::thread.

,那么未定义的行为将变得非常明确

任何理智的程序员都不想调用这种明确定义的行为:破坏可连接的线程会导致调用 std::terminate()std::terminate 的行为依赖于实现,但通常它意味着 "stop right now"。不调用析构函数,不调用退出处理程序。

您需要加入或分离该线程。