I am trying to wait for a thread to die in the destructor of a pure virtual class. The code compiles just fine, and appears to make sense. However, the following error occurs when running it:
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
Here is my program:
#include <boost/thread.hpp>
#include <iostream>
class Test {
protected:
int x;
boost::thread th;
public:
Test(void): x(10) {};
~Test(void);
virtual void operator()(void);
void run(void);
virtual void a(void) = 0;
void wait(void);
};
Test::~Test(void) {
this->wait();
}
void Test::operator()(void) {
this->a();
x += 10;
std::cout << "Current Value: " << x << std::endl;
}
void Test::run(void) {
this->th = boost::thread(&Test::operator(), this);
}
void Test::wait(void) {
this->th.join();
}
class Test1 : public Test {
public:
virtual void a(void);
};
void Test1::a(void) {
x--;
}
main() {
Test1 test;
test.run();
//test.wait();
}
The expected result is 19. I can get it by putting the call to Test::wait()
in main()
before the object leaves scope rather than into the destructor. The exception does not happen when the pure-virtual method a()
is removed from Test
.
My questions then are:
Test::a()
is not in the destructor's call chain?I am guessing that the answer to one will be the answer to the other...
P.S. In case it matters, I am running g++ (GCC) 4.9.1 20140903 (prerelease) on Arch Linux, kernel version 3.17.2-1 in GNU bash, version 4.3.30(1)-release
Problem is related to the problem, when you call a virtual function from constructor/destructor. In this case wait() called from a base destructor - Test::~Test()
, which means that derived class Test1
is already destructed and virtual table updated to base class Test
. Looks like virtual call in separate thread happens after that and you get pure virtual method call. So behavior is like you indirectly call a()
from destructor of Test
.
When you call wait() explicitly it waits before test1
instance being destructed and it works fine.
Unrelated to this problem, dtor of class Test should be virtual, as you have virtual method(s).