Search code examples
c++qtpointersqgraphicssceneqlist

Cleaning up QList and QGraphicsScene to avoid memory leaks


I want to be thorough and clean up to avoid memory and object leaks.

I had the misunderstanding that Qt cleans automatically objects that go out of scope, except pointers need to be deleted manually.

In my code I have a number of QList... example:

void someFunction()
{
    QList<int> x = QList<int>() << 0 << 0 << 0 << 0;
    QList<QImage> y; // filled in some way
    QList<QGraphicsScene*> s;

    s = otherFunction(x, y);
}

QList<QGraphicsScene*> otherFunction(QList<int>& x, const QList<QImage>& y)
{
    QList<QGraphicsScene*> s; 
    s.push_back(this->scene());  // a few times; of course there is some processing...
    return s;
}

void thirdFunction()
{
    QList<int> x = QList<int>() << 0 << 0 << 0 << 0;
    QList<QImage> y; // filled in some way
    QList<QGraphicsScene*> s;

    s = otherFunction(x, y);
    for (int i = 0; i < s.size(); ++i)
    {
        view[i]->setScene(s.at(i)); // view is a QList<QGraphicsView*>
    }
}

Called multiple times, I can see the memory increasing (seen from task manager).

Obviously when items go out of scope, they are not being deleted... I immediately suspected the list of scene pointers.

1) What is the best way to delete them ? Will

qDeleteAll(s);

in someFunction() be enough ? Will it delete the scene pointers, as well as all the QGraphicItems inside the scenes ? or do I need to iterate through the list of scenes, and delete all items ? Do I have to do this :

    for (int i = 0; i < s.size(); ++i)
    {
        s.at(i).clear();
    } // then
    qDeleteAll(s);

2) Do I need to delete the lists of simple variables (int, bool) ?
What about lists of objects, like QImage ?

3) I assumed that removing an item from the scene deletes its pointer. But now I read that, after removing an item from the scene, it needs to be deleted manually. So does

scene().clear();

delete the QGraphicItem pointers that have been added to the scene ? Or should the items be deleted as well using a delete call ?

4) In the thirdFunction, do I have a memory leak ? It seems like I do !!
I can't delete the scenes since I set them onto views... but what happens to the scenes that were assigned to the views already ?
How do I clean that correctly ?


Solution

  • 1. qDeleteAll deletes items in a container using the C++ delete operator. It's also stated in the Qt documentation about QGraphicsScene destructor:

    Removes and deletes all items from the scene object before destroying the scene object

    So it's enough to call qDeleteAll(s).

    2. There is no need to delete lists of basic or Qt types like QList<int> or QList<QImage> as they are deleted when the list is deleted.

    3. QGraphicsScene::clear() removes and deletes all items from the scene. So calling scene().clear(); is enough. It's equivalent to calling :

    qDeletaAll( scene()->items() );
    

    4. Since a view does not take ownership of scene, you should delete the previously assigned scenes using deleteLater() :

    for (int i = 0; i < s.size(); ++i)
    {
        view[i]->scene()->deleteLater();
        view[i]->setScene(s.at(i)); // view is a QList<QGraphicsView*>
    }