2015-10-02 30 views
1

所以我在这里有一个奇怪的情况。我有以下代码:当boost线程创建时shared_ptr从不释放

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

有人对这里发生了什么有所了解吗?

+1

您是否尝试过加入线程?否则,终止程序可能会跳过非全局对象的析构函数。这就是说,为什么不创建一个最小的例子,而不是解释你为了分析问题而做了什么?哦,我忘记了:改用'std :: thread'! –

+0

我相信boost线程会在它们的析构函数中被分离。 –

+0

“MyClassB :: method1”的签名是什么? – NathanOliver

回答

4

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

  • 如果定义BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE:如果* this具有执行的相关线索,调用分离(),不推荐使用
  • BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE:如果线程是可连接呼叫标准::终止。破坏*这个。

因此,您需要明确地连接线程。您可以通过在程序结束时调用boost::thread_group::join_all()来完成此操作。

+0

很好的建议。为thready添加了一个机制,可以正常退出,并释放资源。 – nrcrast

2

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

1

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

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

...do stuff

如果...do stuff不涉及任何分离或加入该线程,所调用的升压不确定的行为。如果您从使用boost::thread切换到使用std::thread,那么未定义的行为将变得非常明确。

这个定义良好的行为是不合理的程序员想要调用的东西:破坏可连接的线程导致调用std::terminate()std::terminate的行为是依赖于实现的,但通常意味着“立即停止”。不调用析构函数,不调用退出处理函数。

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

+0

感谢您的意见。我的多线程编程经验非常少,试图调试我继承的程序中的错误(唉)。我并不知道该程序在退出时线程没有被销毁。添加了一个机制在程序结束时加入该线程。它优雅地退出,并返回资源。 – nrcrast