Hi,
I want my classes to use QExplicitlySharedDataPointer for their shared data. Also I want several classes to reference each other.
We have ClassX and ClassY. ClassX maintains a QList<ClassY>. ClassY references exactly one ClassX. Both classes implement copy constructor and operator=(), like this:
ClassY::ClassY(const ClassY &other) :
d( other.d )
{
}
ClassY &ClassY::operator =(const ClassY &other)
{
d = other.d;
return *this;
}
ClassY::ClassY(const ClassY &other) :
QObject(other.parent()),
d( other.d )
{
}
ClassY &ClassY::operator =(const ClassY &other)
{
d = other.d;
return *this;
}
To copy to clipboard, switch view to plain text mode
When we now use the following code to add/set the values, it leads to circular dependencies between the two classes:
void ClassY::setClassX(const ClassX &classX)
{
d->m_classX = classX;
}
void ClassX::addClassY(const ClassY &classY)
{
d->m_classYList.append(classY);
}
void ClassY::setClassX(const ClassX &classX)
{
d->m_classX = classX;
}
void ClassX::addClassY(const ClassY &classY)
{
d->m_classYList.append(classY);
}
To copy to clipboard, switch view to plain text mode
When we execute the following test, the shared data objects are never being destroyed and leak:
int main(int argc, char *argv[])
{
ClassX x1;
ClassY y1;
x1.addClassY(y1);
y1.setClassX(x1);
return a.exec();
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ClassX x1;
ClassY y1;
x1.addClassY(y1);
y1.setClassX(x1);
return a.exec();
}
To copy to clipboard, switch view to plain text mode
I create the output with the help of incremental IDs for each instance of ClassX, ClassY, ClassXPrivate and ClassYPrivate:
ClassXPrivate 0
ClassX 0
ClassXPrivate 1
ClassX 1
ClassYPrivate 0
ClassY 0
~ClassXPrivate 1
~ClassY 0
~ClassX 0
ClassXPrivate 0
ClassX 0
ClassXPrivate 1
ClassX 1
ClassYPrivate 0
ClassY 0
~ClassXPrivate 1
~ClassY 0
~ClassX 0
To copy to clipboard, switch view to plain text mode
As you can see, ClassYPrivate 1 and ClassXPrivate 0 are never being destructed.
You may download the small example Qt Creator project from my dropbox: http://dl.dropbox.com/u/140012/sharedatatest.zip
I came across this behavious in the libtvdb library, in which each Series has several Seasons, which has several Episodes. Each Season knows its Series and each Episode knows its Season and Series. This leads to HUGE memory leaks, if you scrape several hundred TV shows.
Am I right, with what I am saying? How would you solve this problem?
Greetings Niklas
Bookmarks