I’m just beginning to learn C++ and I’m trying to make Thread class that that has the basic functionality of the Java Thread class. What I’m trying to do is make a class which you subclass, write a Run method (which is pure virtual in the base class) create an object of the subclass call the start method on it and you have thread.
The problem is that in the way I use C++ the dispatch isn’t done correctly – it’s like the Run function isn’t virtual, the Run method of the base class is called.
Here is the code for the header
#ifndef _THREAD_H_
#define _THREAD_H_
#include <pthread.h>
class Thread {
public:
Thread();
void Start();
~Thread();
protected:
virtual void Run() = 0;
private:
static void *RunWrapper(void *);
pthread_t thread;
};
#endif
The implementation
#include "thread.h"
#include <pthread.h>
Thread::Thread() {
}
void Thread::Start() {
pthread_create(&thread, NULL, Thread::RunWrapper, (void *) this);
}
void *Thread::RunWrapper(void *arg) {
Thread *t = (Thread *) arg;
t->Run();
return arg;
}
Thread::~Thread() {
pthread_join(thread, NULL);
}
And the file that actually tries to do something
#include <iostream>
#include "thread.h"
class MyThread : public Thread {
protected:
void Run() {
std::cout << "The thread is runned" << std::endl;
}
};
int main(void) {
MyThread thread;
thread.Start();
return 0;
}
The error I keep getting for the last 10 hours is:
pure virtual method called
terminate called without an active exception
The problem is that your MyThread object in main is destroyed as soon as the main function returns, which likely happens before the new thread actually gets around to calling its Start method.
As part of the destruction process, the vtable will be reset to the vtable of the base class before calling the base class destructor, so when the RunWrapper call later gets run it ends up triggering the pure virtual method error. Calling a method on a destroyed object results in undefined behavior, so anything might happen; this behavior is an accident of how your C++ compiler implements destructors and stack allocation.