pure virtual method called Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
briceandre
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 672
Joined: Tue Aug 31, 2010 6:22 am
Location: Belgium

pure virtual method called

Post by briceandre »

Hello,

I have an application that crashes when it exits. It runs under Windows and Linux with exactly same error displayed :
pure virtual method called
terminate called without an active exception
The error occurs while an object of class wxCmdlineProtocol is destroyed. I have the feeling that this error is caused by the fact that this object inherits from both wxEvtHandler and wxSocketClient. But, I do not see why I would not be allowed to derive from both classes.

Here is the debugger trace :
#0 0x00007ffff2d17165 in raise () from /lib/libc.so.6
#1 0x00007ffff2d19f70 in abort () from /lib/libc.so.6
#2 0x00007ffff35aadc5 in __gnu_cxx::__verbose_terminate_handler() ()
from /usr/lib/libstdc++.so.6
#3 0x00007ffff35a9166 in ?? () from /usr/lib/libstdc++.so.6
#4 0x00007ffff35a9193 in std::terminate() () from /usr/lib/libstdc++.so.6
#5 0x00007ffff35a9a6f in __cxa_pure_virtual () from /usr/lib/libstdc++.so.6
#6 0x0000000000c06330 in GSocket::Shutdown (this=0x1f1fdd0)
at ../../src/unix/gsocket.cpp:592
#7 0x0000000000c015c8 in wxSocketBase::Close (this=0x17feaa0)
at ../../src/common/socket.cpp:295
#8 0x0000000000c010ca in ~wxSocketBase (this=0x17feaa0,
__in_chrg=<value optimized out>) at ../../src/common/socket.cpp:234
#9 0x0000000000c03159 in ~wxSocketClient (this=0x17feaa0,
__in_chrg=<value optimized out>) at ../../src/common/socket.cpp:1237
#10 0x00000000009d4fcd in ~wxCmdlineProtocol (this=0x17fea50,
__in_chrg=<value optimized out>) at ../src/utils/wxcmdprot.cpp:93
Does someone has an idea ?

Or does someone knows if I am allowed to write a class that inherits from both wxEvtHandler and wxSocketClient ?

Regards,
Brice
jfouche
Super wx Problem Solver
Super wx Problem Solver
Posts: 442
Joined: Tue May 06, 2008 4:52 pm
Location: France

Post by jfouche »

It may comes from the fact that both wxSocketClient and wxEvtHandler inherit from wxObject (see diamond inheritance).
I allways try to avoid this. The solution I use when I face this is to create a abstract class that contains one of the parent class.
For example :

Code: Select all

class IListener
{
   wxEvtHandler m_handler;

   ...
};

class MySocketClient : public wxSocketClient, public IListener
{
};
Jérémie
catalin
Moderator
Moderator
Posts: 1618
Joined: Wed Nov 12, 2008 7:23 am
Location: Romania

Post by catalin »

From the error message, a pure virtual method is being called.

How can this happen? Either the base class _type_ is used when calling the method (i.e. maybe explicit "Base::PureVirtualFunc();" ? but should this even compile?) or it is called for a derived but _incompletely built_ type. The latter can probably occur if the same function is called in some situations inside a constructor, or, easier to give an example, if in a thread a _derived_ object is destroyed but from another thread a virtual function is called while the _base_ destructor of same object is executed (that is _after_ the destructor of the derived class containing an implementation of the pure virtual function had executed).

AFAIK wxObject has no pure virtual functions. So IMO the problem is elsewhere.

As usual mentioning the wxW version, posting some (simplified as much as possible) code etc. should help.

p.s. do you call wxSocketBase::Initialize() before using socket [derived] classes?
briceandre
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 672
Joined: Tue Aug 31, 2010 6:22 am
Location: Belgium

Post by briceandre »

I think I found the origin of the problem.

After searches in Internet, it seems that the (only?) way to get a "pure virtual method called" error is when calling a method overloading a pure virtual one... when the object has been destroyed :-)

I cheked my code and this is something equivalent to this (it's far more complex, but the idea is the same) :

Code: Select all

wxCmdlineProtocol& GetInstance()
{
   static wxCmdlineProtocol instance(....);
   return instance;
}
At init, everything works fine because the method is called after wxWidgets has initialised. But, the object instance is destroyed by the c++ runtime after wxWidgets has cleaned-up (or, at least, I think this is the case -> I shall still check...).

I think this is the origin of my problem : the destructor of wxSocketBase invokes internal wxWidgets stuff on objects that have been destroyed before my object is cleaned-up.

I will change the code and perform tests to confirm this.
briceandre
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 672
Joined: Tue Aug 31, 2010 6:22 am
Location: Belgium

Post by briceandre »

Catalin,
The latter can probably occur if the same function is called in some situations inside a constructor, or, easier to give an example, if in a thread a _derived_ object is destroyed but from another thread a virtual function is called while the _base_ destructor of same object is executed (that is _after_ the destructor of the derived class containing an implementation of the pure virtual function had executed).
If the problem is the one I mentionned in my previous post, you were very close to my problem :-)

I use version 2.8.11 of wxWidgets and I do not invoke "wxSocketBase::Initialize()". But with this version of wxWidgets, it is no more necessary, I think.
briceandre
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 672
Joined: Tue Aug 31, 2010 6:22 am
Location: Belgium

Post by briceandre »

JFouche,

Thanks for your answer. I don't think diamond inheritence problem can generate this kind of errors. It can create ambiguity on the function call, and maybe a crash if you call the bad function and if that messes up your app.

I encountered this kind of problems when writing this code, but I simply solved them by mentionning the name of the class whose method should be called :

Code: Select all

((wxSocketClient*)this)->SetEventHandler(*this, SOCKET_ID);
Furthermore, in C++, if you do not explicitly mention virtual inheritance ("class MySocketClient : public virtual wxSocketClient, public virtual wxEvtHandler"), each parent whill have its own wxObject parent instance, which still reduces the risk of such problems.
briceandre
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 672
Joined: Tue Aug 31, 2010 6:22 am
Location: Belgium

Post by briceandre »

Dear all,

I performed tests which confirmed my toughts.

Thanks for you help,
Brice
Post Reply