0

I have a slightly modified version of the thread class copied off the Linux Self Help site that I have used to create a threading base class:

class Thread
{
public:
static void *entry (void *pvArg) { Thread *pobjThread = static_cast<Thread *> (pvArg); pobjThread->run (); }
virtual void run (void) = 0;
};

I have 2 thread classes:

class Item : public Thread

and

class Product : public Thread

class Item starts the thread from the constructor of the function, which class into pthread library to create the thread calling entry with this as the pvArg while class Product creates it's thread later during programme execution.

Now the thing is, class Item works fine. The runfunction is called and processes correctly. However, when class Product calls the same function later, I get:

pure virtual method called

Both class have the same implementation with overloading the run method, but one is called and the other is not.

Why would I suddenly get a pure virtual method called exception?

Thanks.

Update: class Item is different the class Product because Item is declared as a static Item item; in the cpp file and there is only one. class Product is used like a normal object. If I do the same thing to class Product it works fine.

user626201
  • 1,623
  • 3
  • 19
  • 36
  • Are you sure that `Product` isn't derived from `Item`? That would explain the error. – modelnine Apr 10 '12 at 15:17
  • @PlasmaHH - The exception is coming from the class being called normally. Calling from the ctor (of `Item`) is working correctly. – user626201 Apr 10 '12 at 15:17
  • @modelnine - nope, they are distinctly different classes. There is no connection, not even in header includes (other than the thread header). – user626201 Apr 10 '12 at 15:18
  • Then - show the code. pure virtual function called means that the vtable for the instance you're calling run() on isn't properly filled in (yet), which can't happen after all constructor(s) have run (as you cannot instantiate abstract classes). – modelnine Apr 10 '12 at 15:20
  • @user626201: It isn't called "normally". It is called from within the context of the ctor of Thread. – PlasmaHH Apr 10 '12 at 15:22
  • Just seen (forgot about it) the `class Item` is different the `class Product` because `Item` is declared as a `static Item item;` in the cpp file, and there is only one. `class Product` is used like a normal object. If I do the same thing to `class Product` it works fine. Any ideas? – user626201 Apr 10 '12 at 15:26
  • 3
    Most probably, your `Product` is already destroyed (`delete`d) when the thread is started - the vtables are reset on destruction to catch these kind of errors, which also causes a pure virtual function call. – modelnine Apr 10 '12 at 15:27
  • Oh dear, quite right. The offending code is on the stack (part of unit test case)! It will be deleted when the test complete. Thanks, makes sense now :) – user626201 Apr 10 '12 at 15:29

3 Answers3

1

Do not call virtual functions from a constructor or a destructor - the inheritance chain is incomplete when code is running in either, and as such, there's no meaningful way to call virtual functions. See Pure virtual invocation from constructor and destructor for another answer.

Community
  • 1
  • 1
modelnine
  • 1,499
  • 8
  • 11
0

Item and Product are : public Thread means you would call a virtual function (of itself) inside the constructor. Inside the constructor the vtable is not set up fully yet (since it depends on each of base classes being initialized), so you will get undefined behavior.

best practice: dont call virtual functions from inside a constructor/destructor. Keep constructors/destructors very simple, do the rest of the work inside an init() function or such.

skimon
  • 1,149
  • 2
  • 13
  • 26
  • @phresnel: It's only forbidden to call a *pure* virtual function; calling a non-pure function from a constructor is well defined, and might occasionally be a reasonable thing to do. – Mike Seymour Apr 10 '12 at 15:55
  • @MikeSeymour: Somehow I actually read "pure", but I guess my subconscious juggled words too much while reading. – Sebastian Mach Apr 10 '12 at 16:03
0

Thanks to what modelnine pointed out, we found the offending code was creating an object, starting the thread and then destroying the object, before the thread got a chance to run. This, as modelnine indicated, delete's the vtable, and this caused the problem.

Thanks to modelnine in the comments of the question.

user626201
  • 1,623
  • 3
  • 19
  • 36