以下程序崩溃。但我真的不明白为什么。布尔my_shared_resouce在现实生活中是一个异步队列,最终通过消息传递停止线程内部的循环。
但是,以下程序崩溃,因为析构函数似乎被多次调用。第一次它在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-2ubuntu1~14.04)4.8.4
编译为g ++ --std = c ++ 0x thread.cpp -pthread
有人请告诉我这个设计有什么问题。
答案 0 :(得分:3)
复制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;
};
答案 1 :(得分:2)
根据http://en.cppreference.com/w/cpp/thread/thread/thread 你在打电话:
template< class Function, class... Args >
explicit thread( Function&& f, Args&&... args );
其中
创建新的std :: thread对象并将其与执行线程相关联。首先,构造函数将所有参数(包括函数对象f和所有args ...)复制/移动到线程可访问的存储
因此,您的my_shared_resourse
指针会在线程对象的多个副本之间被复制和共享,并在多个位置被销毁。定义适当的复制构造函数/赋值运算符或使用共享指针。