Pure virtual function call before program even begins...

I recently made some big changes to the class structure in my program because I ran into a compatibility issue between two libraries I am using. I moved the locations of pure virtual functions etc... None of those functions however exist outside of classes.

My application compiles fine. No warnings or errors regarding instances of pure virtual objects. But I am now getting a debug error saying I am calling a pure virtual function. I have put break points at the first statement in my "main.cpp" and we don't even get that far before it happens.

My program does use several dlls that are part of the project. So I assume that the problem must be happening when it is loading those dlls.

I do have a curiously recurring template pattern (which was affected by the changes) that calls some static functions that SHOULD exist but that is the only thing I can think of. I will check into that but technically those functions aren't truly virtual (even though they may not exist). Would this cause the kind of error I am getting?

What else could be causing this?

You are talking about breakpoints, so I assume you know how to use a debugger. Post stack trace of the crash here. It would be really useful.
Yeah... I forgot to mention that. There is NO stack trace. No calls are made at all that I can see in the debugger. It is completely blank (which is why I am stuck).
Temporarily replace the pure virtual function with a regular virtual function and put a breakpoint in it. That will give you the stack trace. You are probably instantiating some class instances and the constructor is calling the pure virtual. Not sure how this could happen though.
Ok... if I "Retry" instead of abort, I get some info in the call stack. I will see if I can find the problem using that.
Something like this:
a. constructor of derived class object at namespace scope
b. invokes constructor of base class sub-object
c. which indirectly calls a pure virtual function in the base class.

1
2
3
4
5
6
7
8
9
10
11
12
13
struct A
{
    A() { foo() ; }
    virtual ~A() = default ;
    virtual void foo() const { bar() ; }
    virtual void bar() const = 0 ;
};

struct B : A { virtual void bar() const override {} } ;

B b ;

int main() {}

http://coliru.stacked-crooked.com/a/827959f34e091761
Ok... I found the line causing the issue but I am not sure why it is causing a problem. The problem is in a line that calls a pure virtual function that IS defined in the child class. Why isn't it detecting that the function exists in the child class? Please pay attention to comments in my code as I have pointed out the issues/relevant information with them. Here is the (simplified) relevant class structure:

The bottom base class:
1
2
3
4
5
6
7
8
9
10
11
class APPCORE_EXPORT BaseObject
{
public:
	BaseObject(BaseObjectType type);
	virtual ~BaseBuilderObject();
	BaseObjectType baseObjectType() const;
	virtual char* appObjectName() const = 0; // THIS IS THE VIRTUAL FUNCTION BEING CALLED
private:
	static ObjectManager* sObjectManager;
	BaseObjectType mBaseType;
};


Here is the base class for all objects of the most generally used type. This class has the code that is causing the crash... Note my comments.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// FROM THE HEADER
class BUILDERCORE_EXPORT GeneralObject : public BaseObject
{
public: 
	GeneralObject();
	virtual ~GeneralObject();
	virtual QLatin1String qLatin1Name() const; // THIS FUNCTION causes crash. see source below.
	virtual QString qStringName() const; 
	virtual unsigned int id() const = 0;	

	// NOTE: appObjectName() is NOT defined at this level.  see why below.
};

// FROM THE SOUCE:
// NOTE:... this class does NOT define appObjectName... that must be done in the next
//	inheritance level because the next level deals with the compatibility issue.
QLatin1String BuilderObject::qLatin1Name() const { return QLatin1String(appObjectName()); }


Here is a base class that defines appObjectname() and derives all its object names from one library... (the Qt library which is the only library whose object names I currently use... have yet to implement the other one). The appObjectName() function DOES have a body.
1
2
3
4
5
6
7
8
// FROM HEADER
class APPCORE_EXPORT QtComponent : public GeneralObject
{
	// a bunch of constructors...
	// some irrelevant functions...

	virtual char* appObjectName() const override;
}

Last edited on
I thought you could call implemented functions from within an abstract class. Is this wrong?
I thought you could call implemented functions from within an abstract class. Is this wrong?


No... you can. Just not from a ctor/dtor... which is what I would guess is happening.

Is GeneralObject's ctor trying to call appObjectName? Or is it calling a function that is calling it?
Ok... yeah. That's the problem. Thanks. Hmm... I am going to have to figure out a way around this issue because the object is added by name to the object manager from the constructor in the General Object class.

If I called another method in the class from the constructuor that in tern called the implemented function, would that work? Or would that effectively be the same thing?

I suppose another workaround would be to add the object to the manager from the component class... annoying but unless there is another way I guess it is necessary.
Last edited on
If I called another method in the class from the constructuor that in tern called the implemented function, would that work? Or would that effectively be the same thing?


It'd be the same thing.

In C++, the parent is constructed fully before child construction even begins. So if you attempt to call any virtual functions before the parent ctor completes, it won't do what you expect because the child part of the object doesn't exist yet.


One way around this is to pass the name into the parent ctor so it doesn't have to call anything back:

1
2
3
4
5
6
7
8
9
10
11
12
class GeneralObject
{
    //...
    GeneralObject(const char* name);  // <- change the ctor so that the name is passed in
};


class MyChild : public GeneralObject
{
    //...
    MyChild() : GeneralObject("This Name") { }
};
LOL... ok so I need to undo some changes I made. I should have thought of that myself. Originally I did send the name to the GeneralObject class. Ugh... this library incompatibility is annoying. I made all these changes to avoid having to make a duplicate of the name in the base class because one library doesn't allow me to instantiate its name class with a pointer to another object because it always copies the data regardless of whether or not it is a copy constructor. So I have to have a pure virtual function to grab the actual name.
What about the destructor? I can't call a pure virtual function from there either? That really does present a problem since destructors don't take arguments. I will have to remove from the object manager directly from each inherited objects destructor I imagine.
Member functions, including virtual functions, can be called during construction or destruction. When a virtual function is called directly or indirectly from a constructor or from a destructor, including during the construction or destruction of the class’s non-static data members, and the object to which the call applies is the object (call it x) under construction or destruction, the function called is the final overrider in the constructor’s or destructor’s class and not one overriding it in a more-derived class.

If the virtual function call uses an explicit class member access and the object expression refers to the complete object of x or one of that object’s base class subobjects but not x or one of its base class subobjects, the behavior is undefined. - IS
The destructor presents the same problem, just in reverse. Just as the child class is constructed after the base class, it is destructed before the base class.
What about the destructor? I can't call a pure virtual function from there either? That really does present a problem since destructors don't take arguments. I will have to remove from the object manager directly from each inherited objects destructor I imagine.


Don't do that.

Have the parent class record the name.

Change appObjectName so that it is non-virtual and just return the recorded copy in the parent class.

Then not only do your children not have to override it, but you don't have any ctor/dtor issues.
Topic archived. No new replies allowed.