创建boost线程时,Shared_ptr永远不会释放

Shared_ptr never deallocated when boost threads created

本文关键字:永远 ptr 释放 Shared boost 线程 创建      更新时间:2023-10-16

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

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的析构函数中打印输出,并验证如果创建了该线程,它不会被调用。

有人知道这是怎么回事吗?

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

    BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE:如果*this有一个相关的执行线程,调用detach(), DEPRECATED
  • BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE:如果线程是可连接的调用std::终止。破坏*。

所以你需要显式地连接线程。您可以通过在程序末尾调用boost::thread_group::join_all()来做到这一点。

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

// 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的行为依赖于实现,但通常它意味着"立即停止"。不调用析构函数,不调用退出处理程序。