?
Solved

pure virtual method called

Posted on 2006-07-05
17
Medium Priority
?
2,174 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
Complete VMware vSphere® ESX(i) & Hyper-V Backup

Capture your entire system, including the host, with patented disk imaging integrated with VMware VADP / Microsoft VSS and RCT. RTOs is as low as 15 seconds with Acronis Active Restore™. You can enjoy unlimited P2V/V2V migrations from any source (even from a different hypervisor)

 
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 600 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 400 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

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

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

Storage devices are generally used to save the data or sometime transfer the data from one computer system to another system. However, sometimes user accidentally erased their important data from the Storage devices. Users have to know how data reco…
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 configuring basic necessities in order to use the 2010 version of Data Protection Manager. These include storage, agents, and protection jobs. Launch Data Protection Manager from the deskt…
This tutorial will show how to configure a single USB drive with a separate folder for each day of the week. This will allow each of the backups to be kept separate preventing the previous day’s backup from being overwritten. The USB drive must be s…
Suggested Courses

764 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