Qt World Summit: Submit your Presentation

Clean QList for QMLListProperty

  • Hi,

    I have container QObject that contains QList of QObjects. I use it in QmlListProperty and show it in application.
    I want to rewrite that list in function. So I clear list and append things again.

    for ()
        m_list_Qobjects.append(new Qobject);
    emit listQobjectsChanged(list_Qobject());

    And it works, but obviously memory leaks, because clear() doesn't call delete for stored pointers.

    I tried to delete it:

    m_list_Qobjects.clear(); // It doesn't matter already I think
    for ()
        m_list_Qobjects.append(new myQobject);
    emit listQobjectsChanged(list_Qobject());

    But my application crashes.
    So I thought about another way to solve it, I simply copied pointers to delete them later:

    QList<myQobject *> delList = m_list_Qobjects;
    m_list_Qobjects.clear(); //now it's crucial
    for ()
        m_list_Qobjects.append(new myQobject);
    emit listQobjectsChanged(list_Qobject());
    qDeleteAll(delList); // it stops leaks

    And it actually works. So I tried to make list of those containers (list of lists):

    QList<listQobject *> delList = m_list_listQobjects;
    for ()
        m_list_of_listQobjects.append(new listQobject);
    emit m_list_of_listQobjectsChanged(m_list_of_listQobjects());

    But it crashes again.

    So probably solution wasn't so great at all...
    I suppose there must be some way to safely clean after unnecessary pointers from QList/QmlListProperty.

    I prepared small program to work on that problem specifically, but I'm not sure if should I paste whole project.

  • Lifetime Qt Champion


    AFAIK, the QML engine will take ownership of QObjects without parent (see here) so what is likely to happen is that you are deleting object that are not yours to delete. To avoid that give your objects a parent.`

  • However I did certainly what you said that was only little part.
    Thank for your answer, without it I would only find a way around this issue probably. (like 2 parallel QLists)

    So what works?

    • I make additional QObject with parent "this (list of lists)".
    • Then I make it parent of every QObject I want to delete (QObjects with list and QObjects within lists). I don't change CppOwnership.
    • After that I clear() list and add new QObjects (obsolete QObjects stay accessible as children of that additional QObject).
    • After final emit I delete that QObject with deleteLater(). QPointer isn't necessary here I think. I tried deleteLater in another way of doing things and it crashed, so that is the only way I found.
    • My application deletes QObject and all children with it. With neither crash or leak.
    QObject * delQObject = new QObject (this);
    set_parents_list(delQObject );
    for ()
        m_list_of_listQobjects.append(new listQobject);
    emit m_list_of_listQobjectsChanged(m_list_of_listQobjects());


    listoflistsofQObjects :: set_parents_list(QObject * parent) {
    	for (int i = m_list_of_listQobjects.count(); i>0; i--) {

    Following function isn't necessary if QObjects already have parent that is deleted (like listofQObjects or some QObject inside it). It's safer to make elements children, because then one doesn't need to call deletes in destructor.

    listofQObjects :: set_parents_list(QObject * parent) {
    	for (int i = m_list_ofQobjects.count(); i>0; i--) {

    I don't know if is it "right way", I even found here somebody uses my earlier version with additional list (but it's unsafe for sure).

    The best explanation how to manage memory in qt I found here.

    If there is better way to do so, please share.