Page 1 of 1

pure virtual method called

Posted: Sun Dec 19, 2010 8:05 pm
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

Posted: Sun Dec 19, 2010 9:22 pm
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
{
};

Posted: Sun Dec 19, 2010 11:44 pm
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?

Posted: Mon Dec 20, 2010 6:01 am
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.

Posted: Mon Dec 20, 2010 6:06 am
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.

Posted: Mon Dec 20, 2010 6:21 am
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.

Posted: Mon Dec 20, 2010 4:33 pm
by briceandre
Dear all,

I performed tests which confirmed my toughts.

Thanks for you help,
Brice