Reputation: 4031
This piece of code works as expected (it prints "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;
}
now i do not like the fact that the caller has to know that my class launches a thread! So i would prefere that launching the thread is hidden in my constructor on the run method. So i wrote the following code:
#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;
}
this ends up in the following error:
[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
anyone knows the reason?
Upvotes: 0
Views: 195
Reputation: 180415
When you call c->run();
it executes
void run(){
std::cout << "run()"<<std::endl;
std::thread c_thread(&myClass::procedure,this);
};
When the function ends c_thread
is destroyed. Since you never called join()
or detach()
on it c_thread
is still joinable and this causes the destructor to throws an exception. See std::thread::~thread()
You need to make c_thread
a member of myClass
and in the myClass
destructor you either need to call join()
or detach()
on it. This will allow the thread object to be destroyed without throwing an exception. If you call join()
the destructor will not end until myClass::procedure
ends. If you call detach()
then the destructor will complete immediately but the thread will keep running until the function ends.
Upvotes: 5
Reputation: 8802
c_thread
go out of scope whwn run()
ends, so the thread is destroyed, probably before procedure()
has finished.
I guess you want the std::thread
instance as a member of myClass
, not as a local variable. In this case, the thread is destroyed only when c
go out of scope. Anyway, a thread.join()
in the destructor of myClass
will wait until the thread has completed.
Upvotes: 0