这段代码按预期工作(它打印“procedure()”)
#include <iostream>
#include <thread>
class myClass{
public:
myClass(){};
~myClass(){};
void run(){std::cout << "run()"<<std::endl;};
void procedure(){std::cout << "procedure()"<<std::endl;};
};
int main(int argc, char *argv[]){
myClass* c = new myClass();
std::thread c_thread(&myClass::procedure,c);
c_thread.join();
return 0;
}
现在我不喜欢调用者必须知道我的类启动一个线程的事实!所以我会优先在run方法的构造函数中隐藏启动线程。所以我写了下面的代码:
#include <iostream>
#include <thread>
class myClass{
public:
myClass(){};
~myClass(){};
void run(){
std::cout << "run()"<<std::endl;
std::thread c_thread(&myClass::procedure,this);
};
void procedure(){std::cout << "procedure()"<<std::endl;};
};
int main(int argc, char *argv[]){
myClass* c = new myClass();
c->run();
while(true){}
return 0;
}
这最终会出现以下错误:
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
run()
[New Thread 0x7ffff6fdd700 (LWP 4485)]
terminate called without an active exception
Program received signal SIGABRT, Aborted.
0x00007ffff70135f7 in raise () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.17-106.el7_2.1.x86_64 libgcc-4.8.5-4.el7.x86_64 libstdc++-4.8.5-4.el7.x86_64
(gdb) bt
#0 0x00007ffff70135f7 in raise () from /lib64/libc.so.6
#1 0x00007ffff7014ce8 in abort () from /lib64/libc.so.6
#2 0x00007ffff79179d5 in __gnu_cxx::__verbose_terminate_handler() () from /lib64/libstdc++.so.6
#3 0x00007ffff7915946 in ?? () from /lib64/libstdc++.so.6
#4 0x00007ffff7915973 in std::terminate() () from /lib64/libstdc++.so.6
#5 0x000000000040109d in std::thread::~thread (this=0x7fffffffdeb0, __in_chrg=<optimized out>) at /usr/include/c++/4.8.2/thread:143
#6 0x00000000004011e1 in myClass::run (this=0x606010) at test2.cpp:9
#7 0x0000000000400f65 in main (argc=1, argv=0x7fffffffe008) at test2.cpp:17
(gdb) q
谁知道原因?
答案 0 :(得分:5)
当你致电c->run();
时,它会执行
void run(){
std::cout << "run()"<<std::endl;
std::thread c_thread(&myClass::procedure,this);
};
当函数结束时c_thread
被销毁。由于您从未在其上调用join()
或detach()
c_thread
仍然可以加入,这会导致析构函数抛出异常。见std::thread::~thread()
您需要让c_thread
成为myClass
的成员,并且在myClass
析构函数中,您需要在其上调用join()
或detach()
。这将允许销毁线程对象而不抛出异常。如果您致电join()
,析构函数将不会在myClass::procedure
结束前结束。如果你调用detach()
,则析构函数将立即完成,但线程将继续运行,直到函数结束。
答案 1 :(得分:0)
c_thread
超出范围whwn run()
结束,因此线程被破坏,可能在procedure()
完成之前。
我想你希望std::thread
实例成为myClass
的成员,而不是本地变量。在这种情况下,仅当c
超出范围时才会销毁该线程。无论如何,thread.join()
的析构函数中的myClass
将等到线程完成。