在作用域结束之前调用了析构函数



下面的程序chrash。但我真的不明白为什么。布尔型my_shared_souce在现实生活中是一个异步队列,它最终通过消息传递停止线程内部的循环。但是,以下程序崩溃是因为析构函数似乎被调用了多次。它第一次这样做是在main()中的睡眠结束之前很久。如果我移除delete my_shared_resource;,我可以看到析构函数被调用了三次。。。然而,根据我目前的理解,只有在main()完成时才应该调用析构函数。

#include <thread>
#include <chrono>
#include <iostream>
using namespace std;
class ThreadedClass {
    public:
        ThreadedClass() {
            my_shared_resource = new bool(true);
        }
        virtual ~ThreadedClass() {
            delete my_shared_resource;
            cout << "destructor" << endl;
        }

        void operator()(){
            loop();
        }
        void stop() {
            *my_shared_resource = false;
        }
    private:
        void loop() {
            while (*my_shared_resource) {
                // do some work
                this_thread::sleep_for(std::chrono::milliseconds(1000));
            }
        }
        bool* my_shared_resource;
};
int main(int argc, char** argv) {
    ThreadedClass instance;
    std::thread t(instance);
    this_thread::sleep_for(std::chrono::milliseconds(1000));
    cout << "Did some work in main thread." << endl;
    instance.stop();
    t.join();
    return 0;
}

使用g++编译(Ubuntu 4.8.4-2ubuntu114.04)4.8.4

编译为g++--std=c++0x线程.cpp-phread

有人能告诉我这个设计出了什么问题吗。

复制ThreadedClass时,两个副本都指向同一个my_shared_resource,并且都会将其删除。

使用std::shared_ptr<bool>

class ThreadedClass {
public:
    ThreadedClass() : shared_resource(new bool(true)) { } 
    virtual ~ThreadedClass() { }
    void operator()() { loop(); }
    void stop() { *shared_resource = false; }
private:
    void loop() {
        while (*shared_resource) {
            // Do some work.
            this_thread::sleep_for(std::chrono::milliseconds(1000));
        }
    }
    std::shared_ptr<bool> shared_resource;
};

根据http://en.cppreference.com/w/cpp/thread/thread/thread您正在呼叫:

template< class Function, class... Args > 
explicit thread( Function&& f, Args&&... args );

哪个

创建新的std::thread对象并将其与执行线程相关联。首先,构造函数将所有参数(函数对象f和所有参数…)复制/移动到线程可访问的存储

因此,my_shared_resourse指针在线程对象的多个副本之间被复制和共享,并在多个地方被销毁。定义适当的复制构造函数/赋值运算符或使用共享指针。

最新更新