ustulation
ustulation

Reputation: 3760

c++ : Crash Saying "Pure virtual called"

{ using Visual Studio 2010 , Win7 }

class Base
{
    public:
        Base() : terminateCondition(false)
        {
            //spawn new thread and set entry point to newThreadFunc()
        }

        virtual ~Base() // edited to say it's virtual.
        {
            terminateCondition=true;
            //wait for thread to join
        }

        virtual void vfunc() = 0;

        static void __stdcall newThreadFunc(void *args)
        {
            while(!terminateCondition)
                pThis->vfunc();
        }

        volatile bool terminateCondition;
};

class Derived : public Base
{
    public:
        virtual void vfunc()
        {
            //Do Something
        }
};

Derived* dPtr=new Derived; //now assume pThis is dptr
//later somewhere
delete dPtr;

This code crashes saying pure virtual called. Moving terminateCondition=true to the destructor of Derived prevents this crash. I think i partially get why. Destruction is in reverse order of construction so d'tor of Derived is executed 1st and all functionalities of Derived are destroyed before calling upon the d'tor of Base. In the meantime if pThis->vfunc() is encountered the application would crash. It crashes saying pure virtual called. I could not understand this part. Can someone please explain?

Upvotes: 1

Views: 559

Answers (2)

Alok Save
Alok Save

Reputation: 206596

Your Base class destructor needs to be virtual, Since it is not this code invokes Undefined Behavior.

Reference:
C++03 standard: Section 5.3.5/3:

If the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined.


When you call a virtual function through constructor/destructor the dynamic dispatch does not work as you expect it to.
The type of this in constructor/destructor is of the type of the class who's constructor/destructor is being executed. While you expect the dynamic dispatch to call overidden derived class method Derived::vfunc(), it ends up in a call to Base::vfunc() which does not have a definition and hence results in Undefined Behavior.

Reference:
C++03 Standard 10.4/6:

"Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call (10.3) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined."

Upvotes: 5

usta
usta

Reputation: 6869

This happens because in your code vfunc can be invoked while Base::Base() isn't finished yet or Base::~Base() already started. Both of these cases will invoke undefined behavior, usually manifested as "pure virtual call" error. Reason for it being an error is that the "virtual" mechanism doesn't kick in until after the constructor of most derived object's class started running, and the "virtual" mechanism is no longer in effect after the destructor of most derived object's class finished running. So when you make a call to a virtual function while a constructor or destructor is executing on the object, the corresponding function of the class of which the constructor or destructor is executing will be called. And if that function happens to be pure virtual, the behavior is undefined.

ISO/IEC 14882:2003, 10.4/6: Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call (10.3) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined.

Upvotes: 2

Related Questions