PDA

View Full Version : QSharedPointer does not handle multiple inheritance correctly?



chca
30th January 2011, 18:28
Hello,

I have detected a very annoying issue with QSharedPointer and multiple inheritance. The following code gives a simplified example of the situation in my application (using Qt 4.7.0 on 64 bit Linux):




#include <QtCore>

class A
{
int dataA;
public:
virtual void funcA() { }
};

class Interface
{
public:
virtual void funcIf()=0;
};

class B : public A, public Interface
{
public:
virtual void funcA() { }
virtual void funcIf() { }
};

int main()
{
QSharedPointer<B> pB = QSharedPointer<B>(new B());
QSharedPointer<Interface> pInterface = pB;

pB.clear();
pInterface.clear();

return 0;
}


When trying to run this program, I get a

*** glibc detected *** ./qsharedptr_test: double free or corruption (out): 0x00000000017d0740 ***

error. Valgrind says

==7749== Invalid free() / delete / delete[]
==7749== at 0x4C27A83: operator delete(void*) (vg_replace_malloc.c:387)
==7749== by 0x400BA4: main (in /home/cc/temp/qsharedptr_test/qsharedptr_test)
==7749== Address 0xa267840 is 16 bytes inside a block of size 24 alloc'd
==7749== at 0x4C28973: operator new(unsigned long) (vg_replace_malloc.c:261)
==7749== by 0x4008FE: main (in /home/cc/temp/qsharedptr_test/qsharedptr_test)

Obviously, QSharedPointer does not delete the original pointer to the address of B as I would expect. Does QSharedPointer not correctly handle multiple inheritance, even for abstract classes?

Added after 15 minutes:

By the way, boost::shared_ptr works fine in this case:



#include <boost/shared_ptr.hpp>

class A
{
int dataA;
public:
virtual void funcA() { }
};

class Interface
{
public:
virtual void funcIf()=0;
};

class B : public A, public Interface
{
public:
virtual void funcA() { }
virtual void funcIf() { }
};

int main()
{
using namespace boost;

shared_ptr<B> pB = shared_ptr<B>(new B());
shared_ptr<Interface> pInterface = pB;

pB.reset();
pInterface.reset();

return 0;
}

Zlatomir
30th January 2011, 18:35
Don't you need virtual destructor in your case?
Try this code:

#include <QtCore>
#include <QDebug>
#include <iostream>

class A
{
int dataA;
public:
virtual void funcA() { }
virtual ~A() { qDebug() << "A d-tor";}
};

class Interface
{
public:
virtual void funcIf()=0;
virtual ~Interface() {qDebug() << "Interface d-tor";}
};

class B : public A, public Interface
{
public:
virtual void funcA() { }
virtual void funcIf() { }
~B() {qDebug() << "B d-tor";}
};

int main()
{
QSharedPointer<B> pB = QSharedPointer<B>(new B());
QSharedPointer<Interface> pInterface = pB;

pB.clear();
pInterface.clear();

std::cin.get();
return 0;
}

chca
30th January 2011, 20:07
Indeed, that solves the issue (yes, I should add a virtual destructor to *every* class). Thanks a lot.

Zlatomir
30th January 2011, 20:32
Not all classes should have virtual destructor, only those meant to be inherited.