"pure virtual method called" when implementing the boost :: thread bypass interface

I have a small shell that centralizes what is relative to threads:

class Thread { protected: boost::thread *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() {} }; 

IN:

 A a; a.run(); 

I got a completion with an image of a fairly clean virtual method. I think this is an argument to boost :: bind, but I don’t know how to say "Use virtual clean implementation" ...

Thanks in advance.

Yours faithfully,

Mr mr

+6
c ++ multithreading boost pure-virtual
source share
2 answers

Your failure occurs only when your program immediately exits: it calls the class A destructor, which ends, and calls the thread destructor before the new thread can be scheduled. Then the thread calls your virtual function, but class A no longer exists, so it can call Thread do_work (), which calls pure virtual work (). Here is your program with additional outputs:

 run() started run() ended ~A() started ~A() ended ~Thread() started catch_up() started do_work() started pure virtual method called 

In my opinion, this behavior is undefined, because the object has already expired (the call to the destructor has begun) when a reference to it ( boost::ref(*this) ) was used to call do_work () from the stream.

Solution: let your thread execute before you destroy your object:

 A a; a.run(); a.catch_up(); 

Or, as the boost.thread documentation says, "The Boost.Thread user needs to make sure the object mentioned survives the newly created thread of execution."

+6
source share

I go 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 is not already running, calling catch_up() in the destructor will start the boost stream using Thread vtable, not A, as in C ++ at the point of the destructor. The vtable corresponds to the scope of the destructor type, not the most derived vtable.

+1
source share

All Articles