简体   繁体   English

使用线程销毁类析构函数中的shared_ptr成员变量

[英]Destroying a shared_ptr member variable in the class destructor using a thread

I am trying to recreate destroying a shared_ptr member variable in the bar class destructor using a thread which I feel may be the reason for a heap corruption. 我正在尝试使用一个thread创建重新破坏销毁bar类析构函数中的shared_ptr成员变量,我认为这可能是堆损坏的原因。 I personally feel it is strange to use a thread in a destructor, so I want the opinion from SO. 我个人觉得在析构函数中使用线程很奇怪,所以我希望得到SO的意见。

The pointer may outlive the application , so using detach is more desirable. 指针可能会超出应用程序的寿命,因此使用detach更可取。 The destructor is not called if detach used, however it works if join . 如果使用detach ,则不会调用析构函数,但是如果join ,则可以使用。

1) Is it wrong to reset a smart pointer this way? 1)这样重置智能指针是否错误?

2) Why the destructor is not called when std::thread::detach() was used ? 2)为什么在使用std::thread::detach()时不调用析构函数?

#include <iostream>
#include <thread>
#include <memory>
#include <chrono>

using namespace std;

class foo
{
    public:
    foo(){longcomputation();}
    void longcomputation() 
    { 
        std::cout<<" long computation called \n";
        std::this_thread::sleep_for(std::chrono::seconds(1)); 
    }
};

class bar
{
    public:
    bar(): foo_(std::make_shared<foo>()) {}
    ~bar() 
    {
        std::thread([foo = std::move(foo_)] () mutable
        {
          foo.reset();
          std::cout<<" bar dctor called \n";
        }).detach();  // ==========> works with join however
    }
    private:
    std::shared_ptr<foo> foo_;
};



int main()
{
    bar bar1;
    std::this_thread::sleep_for(std::chrono::seconds(3));
    std::cout << "Exiting\n";
}

This does look like a bad way to handle threads and smart pointers and though I am not some C++ Guru, I would say this is a bad way to code in C++ overall (there will almost surely be issues of readability maintainability etc.). 这看起来确实是处理线程和智能指针的一种不好的方式,尽管我不是C ++专家,但我会说这是在C ++总体上进行编码的一种不好的方式(几乎肯定会存在可读性,可维护性等问题)。

Coming to the destructor, before the detached thread could be scheduled, the destructor exits, destroying the foo_ object and hence, std::move(foo_) fails. 进入析构函数之前,在可以调度分离线程之前,析构函数将退出,破坏foo_对象,因此std::move(foo_)失败。 And when you use join() instead of detach() , you are making the destructor wait for the thread, which is why it works. 当使用join()而不是detach() ,您使析构函数等待线程,这就是它起作用的原因。 It would also work if we build a sleep in the destructor after detaching the thread: 如果在分离线程后在析构函数中建立睡眠,这也将起作用:

~bar()
{
    std::thread([foo = std::move(foo_)] () mutable
    {
      foo.reset();
      std::cout<<" bar dctor called \n";
    }).detach();  // ==========> works with join however
    // this works too
    std::this_thread::sleep_for(std::chrono::seconds(1));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM