Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Creating a QAbstractListModel on the stack and passing to QML



  • Hi!
    I have a question regarding the following construct:

    Suppose you find this function in the data function of a class derived from QAbstractListModel, which is exposed to QML via a context property. The class "OtherModel" is another class derived from QAbstractListModel.

    //[...]
    switch(role) {
    case OtherModelRole: {
            QSharedPointer<OtherModel> model = QSharedPointer<OtherModel>(new OtherModel());
            model->addData(dataprovider->data());
            return QVariant::fromValue(model);
        }
    }
    //[...]
    
    

    What I am trying to accomplish is that a delegate may request additional information from the model, which again is represented in a different type of model (in this example "OtherModel"). I would like to create this data on demand and would rather avoid storing it somewhere. The motivation here is to use QSharedPointer to manage the lifetime of this object and have it safely cleaned up after the model view is closed or otherwise utilized.

    Although the code snippet seems to work just fine at first, it sporadically leads to a crash, sometimes involving heavy scrolling, sometimes just opening the model. What I suppose happens here is that the lifetime of the QSharedPointer is managed by the C++ back end which leads to deletion sooner or later, thus causing a read access violation at some point.

    Now my question is:
    Is there an alternative to this construct which allows me the same flexibility, or maybe even something better?
    Are my assumptions about why the application is crashing correct? I was fighting a nasty heap error over the last couple days which involved me passing a reference to a QAbstractListModel rather than a pointer to QML and I am trying to understand this connection better.

    Thank you!

    Edit: The stack trace of the crash:

    1   QQmlAdaptorModel::setModel                                                                                     qqmladaptormodel.cpp         943  0x6558d7ab 
    2   QQmlAdaptorModel::objectDestroyed                                                                              qqmladaptormodel.cpp         1018 0x6558dbbf 
    3   QQmlData::destroyed                                                                                            qqmlengine.cpp               1951 0x658414ed 
    4   QQmlData::destroyed                                                                                            qqmlengine.cpp               795  0x65840d52 
    5   QObject::~QObject                                                                                              qobject.cpp                  920  0x66642962 
    6   QAbstractItemModel::~QAbstractItemModel                                                                        qabstractitemmodel.cpp       1553 0x665879d6 
    7   QAbstractListModel::~QAbstractListModel                                                                        qabstractitemmodel.cpp       3743 0x6658b8f8 
    8   OtherModel::~OtherModel                                                                        
    9   OtherModel::scalar deleting destructor                                                           
    10  QtSharedPointer::CustomDeleter<OtherModel,QtSharedPointer::NormalDeleter>::execute                     qsharedpointer_impl.h        195  0xe2e270   
    11  QtSharedPointer::ExternalRefCountWithCustomDeleter<OtherModel,QtSharedPointer::NormalDeleter>::deleter qsharedpointer_impl.h        217  0xe2dd05   
    12  QtSharedPointer::ExternalRefCountData::destroy                                                                 qsharedpointer_impl.h        157  0xd17f59   
    13  QSharedPointer<OtherModel>::deref                                                                      qsharedpointer_impl.h        467  0xe2dd77   
    14  QSharedPointer<OtherModel>::deref                                                                      qsharedpointer_impl.h        460  0xe2dd23   
    15  QSharedPointer<OtherModel>::~QSharedPointer<OtherModel>                                        qsharedpointer_impl.h        
    


  • I don't have a solution for you I'm afraid but I can confirm that I also saw crashes when I tried to do something similar. In my case I was trying to implement a "tree and property table view" such that selecting a branch of the tree shows properties associated with that branch in the table below. I was doing something quite similar to you and, similarly, it seemed to work at first but would crash at some point.

    In the end, I resolved it by avoiding allocating my property models on the fly but instead had a single 'persistent' model object whose content is adjusted depending on the current branch selection. This worked for me because there is only one visible property table.



  • That's the solution I usually choose when encountering such a problem, but in my case there can be multiple views open at the same time, which do not need to be in sync.
    If anyone else has a suggestion how to resolve this problem I am open to suggestions.