boost thread destroys polymorphism
duplicate of: "pure virtual method called" when implementing a boost::thread wrapper interface
I am trying to create a more object oriented version of the threads using boost threads.
So I created a Thread class:
class Thread {
public:
Thread() {}
virtual ~Thread() { thisThread->join(); }
void start() { thisThread = new boost::thread(&Thread::run, this); }
virtual void run() {};
private:
boost::thread *thisThread;
};
this class creates the thread in start() l开发者_JS百科ike this:
thisThread = new boost::thread(&Thread::run, this);
The problem is that when I create a class that overwrites the run()
method, the run()
method from Thread is call by the thread instead of the new run()
method
for example I have a class that extends Thread:
class CmdWorker: public Thread {
public:
CmdWorker() : Thread() {}
virtual ~CmdWorker() {}
void run() { /* deosn't get called by the thread */ }
};
when I do
Thread *thread = new CmdWorker();
thread.start(); //---> calls run() from Thread instead of run() from CmdWorker
but just to be more clear:
thread.run(); calls the correct run from CmdWorker, (run() is virtual from Runnable)
Any idea why this happens or how it can be fixed ?
NOTE: I created a function (that has nothing to do with the Thread class)
void callRun(Thread* thread) {
thread->run();
}
and changed the thread creation to:
thisThread = new boost::thread(callRun, this);
when debugging I noticed that the thread
pointer is pointing to a object of type Thread instead of CmdWorker
EDIT:
testcase code at: http://ideone.com/fqMLF and http://ideone.com/Tmva1
Object seems to be sliced (but this is strange since pointers are used)
didn't manage to add boost to it
The answer is in that question:
"pure virtual method called" when implementing a boost::thread wrapper interface
Basically, when the boost::thread object begins running, the object it was run against had the time to be deleted.
You have to implement a join
method that you call manually before destroying the object.
when debugging I noticed that the thread pointer is pointing to a object of type Thread instead of CmdWorker
Maybe the CmdWorker
object is sliced (i.e. copied by value) into a Thread
object somewhere in your code?
Do you get the same behaviour with a minimal test case?
By doing &Thread::Run
on a non-virtual function, you are forcing any class that derives from Thread to use the function specified in the Thread base class. Try making Thread::Run a virtual void and see if that fixes your issue.
From reading your updates, you're calling delete in the main thread, while the thread is starting in the other. Depending on the race between the destructor and the invocation of run
, it will either:
- Crash before it starts, because the vtable is completely destroyed
- Call the Thread::run (which is pure virtual, and crashes with a pure virtual thunk)
- Call the correct function, which is the derived class run()
If you add a call to sleep(1)
after you call start, but before you call delete
, you'll find that it works as you expect.
精彩评论