Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

pure virtual method called

Posted on 2006-07-05
17
Medium Priority
?
2,182 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
 [eBook] Windows Nano Server

Download this FREE eBook and learn all you need to get started with Windows Nano Server, including deployment options, remote management
and troubleshooting tips and tricks

 
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

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!

Question has a verified solution.

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

Are you looking to recover an email message or a contact you just deleted mistakenly? Or you are searching for a contact that you erased from your MS Outlook ‘Contacts’ folder and now realized that it was important.
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
This tutorial will walk an individual through configuring a drive on a Windows Server 2008 to perform shadow copies in order to quickly recover deleted files and folders. Click on Start and then select Computer to view the available drives on the se…
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…

636 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