I have a small wrapper which centralize what's relative to threads :
class Thread {
protected:
boost::thread *开发者_C百科m_thread;
virtual void work() = 0;
void do_work() {
work();
}
public:
Thread() : m_thread(NULL) {}
virtual ~Thread() {
catch_up();
delete m_thread;
}
inline void catch_up() {
if(m_thread != NULL) {
m_thread->join();
}
}
void run() {
m_thread = new boost::thread(boost::bind(&Thread::do_work, boost::ref(*this)));
}
};
When I implement it, say with the following :
class A : public Thread {
void work() {}
};
At :
A a; a.run();
I got a runtime termination with a pretty "pure virtual method called" displayed. I think it's the boost::bind argument, but I don't know how to say "Use virtual pure implementation"...
Thanks aforehand.
Regards,
Mister Mystère
Your crash happens only when your program exits immediately: it calls class A's destructor which finishes and calls Thread's destructor before the newly started thread had a chance to be scheduled. The thread then calls your virtual function, but class A no longer exists, so it attemps to call Thread's do_work(), which calls the pure virtual work(). Here's your program with extra outputs:
run() started
run() ended
~A() started
~A() ended
~Thread() started
catch_up() started
do_work() started
pure virtual method called
Standard-wise, I think this is undefined behavior because the object's lifetime has already ended (destructor call began) when a reference to it (boost::ref(*this)
) was used to call do_work() from the thread.
Solution: let your thread execute before you destruct your object:
A a; a.run();
a.catch_up();
Or, as boost.thread documentation says, "the user of Boost.Thread must ensure that the referred-to object outlives the newly-created thread of execution."
I'm going out on a limb here, but I suspect the problem is with your Thread destructor:
virtual ~Thread() {
catch_up();
delete m_thread;
}
If the thread hasn't started yet, calling catch_up()
in the destructor will start the boost thread using Thread's vtable rather than A's, as in C++ at the point of the destructor the vtable matches the scope of the type of the destructor, not the most derived vtable.
精彩评论