Solved

pure virtual method called

Posted on 2006-07-05
17
2,169 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
Ransomware: The New Cyber Threat & How to Stop It

This infographic explains ransomware, type of malware that blocks access to your files or your systems and holds them hostage until a ransom is paid. It also examines the different types of ransomware and explains what you can do to thwart this sinister online threat.  

 
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

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

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

Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
In this article we will learn how to backup a VMware farm using Nakivo Backup & Replication. In this tutorial we will install the software on a Windows 2012 R2 Server.
To efficiently enable the rotation of USB drives for backups, storage pools need to be created. This way no matter which USB drive is installed, the backups will successfully write without any administrative intervention. Multiple USB devices need t…
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.

724 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