Solved

pure virtual method called

Posted on 2006-07-05
17
2,166 Views
Last Modified: 2013-11-15
It is a multi-threaded daemon on a Linux box (GCC). In 1 out of 10 start-ups, it aborts with a "pure virtual method called" error. It is not bombing out during static initialisation. It occurs in main(), but there are several threads on the go or initialising at the time. Alas, it only happens in the release build.

The only thing I can think that would cause a PVM call would be if a base constructor called a base function, which called a PVM, and I'm sniffing down that track.

i.e.
--------8<--------
struct base
{
      base() {init();} // Ctor calls a function, which calls a PVM
      void init() {f();} // Calls a PVM
      virtual void f() = 0;
};

struct derived : public base {virtual void f(){}};

int main()
{
      Derived d;
}
--------8<--------

Are there any other circumstances the panel can think of, which would result in a PVM call?
0
Comment
Question by:rstaveley
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 4
  • 3
  • +1
17 Comments
 
LVL 5

Expert Comment

by:bastibartel
ID: 17041281
Hi there,

Upon construction of d your code exectues:

base::base()
   base::init()
      base::f()     // derived hasn't been constructed yet. check out the vtable in the debugger in base::init()

If you call f() after derived::derived() has been entered it works.

//---- snip -------------------------

struct base
{
     base()
     {
           //** too early to call derived::f()
           /**  init()
     }
     void init()
     {
          f();
     }
     virtual void f() = 0;
};

struct derived : public base
{
    derived()
    {
         init();  // now it works
    }
    virtual void f(){}

};

int main()
{
     Derived d;
}
0
 
LVL 17

Author Comment

by:rstaveley
ID: 17041328
Yes, bastibartel, that was supposed to be an illustration of the only way I know to cause a a "pure virtual method called" error. I wasn't looking for a way to fix the illustration :-D

My question is:

> Are there any *other* circumstances the panel can think of, which would result in a PVM call
0
 
LVL 30

Expert Comment

by:Axter
ID: 17041330
Hi rstaveley,
bastibartel is absolutely correct.
Your base class should avoid calling virtual functions in its constructor and in its destructor.


David Maisonave (Axter)
Cheers!
0
NEW Veeam Agent for Microsoft Windows

Backup and recover physical and cloud-based servers and workstations, as well as endpoint devices that belong to remote users. Avoid downtime and data loss quickly and easily for Windows-based physical or public cloud-based workloads!

 
LVL 17

Author Comment

by:rstaveley
ID: 17041337
Et tu, David?

My question is:

> Are there any *other* circumstances the panel can think of, which would result in a PVM call
0
 
LVL 30

Accepted Solution

by:
Axter earned 150 total points
ID: 17041338
rstaveley,
> > Are there any *other* circumstances the panel can think of, which
> would result in a PVM call
Calling a virtual function from the base destructor.

David Maisonave (Axter)
0
 
LVL 17

Author Comment

by:rstaveley
ID: 17041340
...though the destructor call is a good point :-)
0
 
LVL 17

Author Comment

by:rstaveley
ID: 17041346
Damn there's some fast posting going on!
0
 
LVL 30

Expert Comment

by:Axter
ID: 17041355
Sorry rstaveley.
When I posted my first two comments, I didn't pay attention to the name of the questioner.
Otherwise, I would have read the question differently.

David Maisonave (Axter)
0
 
LVL 5

Assisted Solution

by:bastibartel
bastibartel earned 100 total points
ID: 17041375
lol - I am sorry, rstaveley.
Oh noooo - not you again Axter ;-)

0
 
LVL 17

Author Comment

by:rstaveley
ID: 17041847
Oh crumbs... I should be shot. I just spotted this in a constructor complete with my comment:

>      // This class is self-registering. Not cool? Shouldn't be IMHO.
>      handler.Add(this);      

That definitely wasn't a clever thing to do. Let's keep this as our secret in the privacy of the...erm Internet. I think I'll go off and apply for a managerial job %-}

The moral of the story is: never think you can get away with passing a reference/pointer to a base class, but especially don't do it in an MT application.
0
 
LVL 30

Expert Comment

by:Axter
ID: 17042190
>>Oh noooo - not you again Axter ;-)

Actually, this is my usual hang out.
I rarely post in the other topic areas.
0
 
LVL 5

Expert Comment

by:bastibartel
ID: 17042290
What's your local time - maybe we can co-exist in temporally separated universes. It's 3pm here.

Have a good day :)
Sebastian
0
 
LVL 17

Author Comment

by:rstaveley
ID: 17042514
Sebastian, if you've had your nose bloodied by David in another question, take my word for it that it is almost certainly because he has a deep affection for his subject, and the struggle is much more likely to have been for truth than personal rivalry.

Best wishes and respect to you both

    Rob
0
 
LVL 4

Expert Comment

by:havman56
ID: 17048780
This is for info .
need clarification why linker error

when i compiled the above code i am getting linker error in vc6 (lnk 2001) when i call PVM directly in ctor . but where as PVM called via interface in ctor crashes as ur program .

when u call PVM in base class constructor then u need to provide implementation


class Base
{
public:
      Base();
      virtual ~Base();
      void init();
      virtual void func()=0;
      
};

class Derived :public Base
{
public:
      Derived();
      virtual ~Derived();
      virtual void func();
};

Derived d;

// this crashes ctor is calling interface which in turn calls PVM . crashes same as ur problem
Base::Base() { init(); }
void Base::init(){func(); }

// Gives linker error . bit confused
 Base::Base(){ func(); }
0
 
LVL 17

Author Comment

by:rstaveley
ID: 17049090
// Gives linker error . bit confused
 Base::Base(){ func(); }

Oddly enough, it is quite correctly a linker error and not a compiler error. It expects a *default PVF* to have been defined for void Base::func() = 0.

Add this to your code and you avoid the linker error:
--------8<--------
/* A PVF default definition!! Yes you *can* define a function body for a pure virtual function */
void Base::func()
{
}
--------8<--------

Default PVFs have their uses.
0
 
LVL 4

Expert Comment

by:havman56
ID: 17050600
my question is ctor-->initi-->func() why no linker error ?

but ctor-->func() linker error  why

0
 
LVL 17

Author Comment

by:rstaveley
ID: 17050692
The first makes a dynamic call, using the virtual method table. The second implicitly makes a static call.

As I said in your question, it would be better if the compiler warned you that it was assuming a static call.

When you write...

    Base::Base(){ func(); }

...the compiler interprets it as a static call, because you are still in the constructor - i.e.

    Base::Base(){ Base::func(); }

A static call does not use the virtual method table.

When you write....

   void Base::init(){func(); }

...the compiler interprets it as a dynamic call and looks for the function pointer in the virtual method table.
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Least Squares Curve Fitting 4 114
How can i compile this github project?? 2 97
Gaming Software 1 28
Finding Divisors 5 35
How to fix error ""Failed to validate the vCentre certificate. Either install or verify the certificate by using the vSphere Data Protection Configuration utility" when you are trying to connect to VDP instance from Vcenter.
Microservice architecture adoption brings many advantages, but can add intricacy. Selecting the right orchestration tool is most important for business specific needs.
This tutorial will walk an individual through the process of installing of Data Protection Manager on a server running Windows Server 2012 R2, including the prerequisites. Microsoft .Net 3.5 is required. To install this feature, go to Server Manager…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

740 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question