PDA

View Full Version : Crash in Qml destkop application.



JanW
15th December 2016, 15:57
Hi,

I'm working on a medium sized desktop application, where the UI is made with QML. At the leftside of the application, we have a toolbar with 4 buttons which determine in which layout you are working. Each layout has a different set of toolbars and a docking view(with docked windows inside and a 3d render window). When switching between the layouts, the toolbars change, the docking view changes (with different number of docked windows with different content) and the render window changes. Just to say that a lot changes when you switch between layouts. Once in a while, when switching between layouts, the application just crashes. I found a repeatable sequence of actions to make it crash, but I'm completely lost where to go from here. At the moment I change the layout, i set a context property to a new pointer which triggers all the updates and at one point somewhere deep in qt5qml.dll an assert is triggered. The complete call stack (from VS2013) looks as follows:



Qt5Cored.dll!qt_message_fatal(QtMsgType __formal, const QMessageLogContext & context, const QString & message) Line 1673 C++
Qt5Cored.dll!QMessageLogger::fatal(const char * msg, ...) Line 793 C++
Qt5Cored.dll!qt_assert(const char * assertion, const char * file, int line) Line 3064 C++
Qt5Qmld.dll!QQmlAbstractBinding::~QQmlAbstractBind ing() Line 56 C++
Qt5Qmld.dll!QQmlBinding::~QQmlBinding() Line 144 C++
[External Code]
Qt5Cored.dll!QMetaObject::cast(const QObject * obj) Line 366 C++
Qt5Cored.dll!QMetaObject::cast(QObject * obj) Line 356 C++
Qt5Qmld.dll!qobject_cast<QObject * __ptr64>(QObject * object) Line 517 C++
Qt5Qmld.dll!QtPrivate::QVariantValueHelper<QObject * __ptr64>::object(const QVariant & v) Line 710 C++
Qt5Qmld.dll!QtPrivate::ObjectInvoker<QtPrivate::QVariantValueHelper<QObject * __ptr64>,QVariant const & __ptr64,QObject * __ptr64>::invoke(const QVariant & a) Line 103 C++
Qt5Qmld.dll!qvariant_cast<QObject * __ptr64>(const QVariant & v) Line 836 C++
Qt5Qmld.dll!VDMObjectDelegateDataType::createItem( QQmlAdaptorModel & model, QQmlDelegateModelItemMetaType * metaType, QQmlEngine * __formal, int index) Line 761 C++
Qt5Qmld.dll!QQmlAdaptorModel::createItem(QQmlDeleg ateModelItemMetaType * metaType, QQmlEngine * engine, int index) Line 126 C++
Qt5Qmld.dll!QQmlDelegateModelPrivate::object(QQmlL istCompositor::Group group, int index, bool asynchronous) Line 936 C++
Qt5Qmld.dll!QQmlDelegateModel::object(int index, bool asynchronous) Line 1023 C++
Qt5Quickd.dll!QQuickRepeaterPrivate::requestItems( ) Line 400 C++
Qt5Quickd.dll!QQuickRepeater::regenerate() Line 395 C++
Qt5Quickd.dll!QQuickRepeater::componentComplete() Line 348 C++
Qt5Qmld.dll!QQmlObjectCreator::finalize(QQmlInstan tiationInterrupt & interrupt) Line 1218 C++
Qt5Qmld.dll!QQmlIncubatorPrivate::incubate(QQmlIns tantiationInterrupt & i) Line 354 C++
Qt5Qmld.dll!QQmlEnginePrivate::incubate(QQmlIncuba tor & i, QQmlContextData * forContext) Line 95 C++
Qt5Qmld.dll!QQmlComponent::create(QQmlIncubator & incubator, QQmlContext * context, QQmlContext * forContext) Line 1067 C++
Qt5Quickd.dll!QQuickLoaderPrivate::_q_sourceLoaded () Line 723 C++
Qt5Quickd.dll!QQuickLoaderPrivate::load() Line 604 C++
Qt5Quickd.dll!QQuickLoader::componentComplete() Line 815 C++
Qt5Qmld.dll!QQmlObjectCreator::finalize(QQmlInstan tiationInterrupt & interrupt) Line 1218 C++
Qt5Qmld.dll!QQmlIncubatorPrivate::incubate(QQmlIns tantiationInterrupt & i) Line 354 C++
Qt5Qmld.dll!QQmlEnginePrivate::incubate(QQmlIncuba tor & i, QQmlContextData * forContext) Line 95 C++
...


I know it's kinda long shot, but is there anybody who has an idea what could be the problem, or how I could find a starting point to look further. I already when through the call stack and checked some members to see if i could find a text or a class from my side, or a link to a qml file, but the only thing i see is internal qt code which I'm totally not familiar with.

I narrowed the problem down a little bit. In each layout we have something called a viewmanager. It's basically a tabview with a tab for each type of item in the scene which are important for that layout. The model for the tabView is a


Q_PROPERTY(QQmlListProperty<ViewManagerTabQMLInterface> tabsList READ getTabsList NOTIFY tabsListChanged);


the member QList is a


QList<ViewManagerTabQMLInterface*> _tabsList;

the implementation for getting the tabs is like this:


//--------------------------------------------------------------------------------------
/// Returns the tablist
//--------------------------------------------------------------------------------------

QQmlListProperty<ViewManagerTabQMLInterface> ViewManagerQMLInterface::getTabsList()
{
return QQmlListProperty<ViewManagerTabQMLInterface>(this, 0, &appendTab, &tabCount, &tabAt, &tabClear);
}

//--------------------------------------------------------------------------------------
/// Appends a tab
//--------------------------------------------------------------------------------------

void ViewManagerQMLInterface::appendTab(QQmlListPropert y<ViewManagerTabQMLInterface>* list, ViewManagerTabQMLInterface* p) {
ViewManagerQMLInterface* vm = qobject_cast<ViewManagerQMLInterface*>(list->object);
if (vm && p) {
vm->_tabsList.append(p);
emit vm->tabsListChanged();
}
}

//--------------------------------------------------------------------------------------
/// Returns the number of tabs
//--------------------------------------------------------------------------------------

int ViewManagerQMLInterface::tabCount(QQmlListProperty<ViewManagerTabQMLInterface>*list)
{
ViewManagerQMLInterface* vm = qobject_cast<ViewManagerQMLInterface*>(list->object);
if (vm)
return vm->_tabsList.count();
return 0;
}

//--------------------------------------------------------------------------------------
/// Returns the tab at the given index
//--------------------------------------------------------------------------------------

ViewManagerTabQMLInterface* ViewManagerQMLInterface::tabAt(QQmlListProperty<ViewManagerTabQMLInterface>* list, int i)
{
ViewManagerQMLInterface* vm = qobject_cast<ViewManagerQMLInterface*>(list->object);
if (vm)
return vm->_tabsList.at(i);
return 0;
}

//--------------------------------------------------------------------------------------
/// Clears all the tabse
//--------------------------------------------------------------------------------------

void ViewManagerQMLInterface::tabClear(QQmlListProperty<ViewManagerTabQMLInterface> *list)
{
ViewManagerQMLInterface* vm = qobject_cast<ViewManagerQMLInterface*>(list->object);
if (vm){
vm->_tabsList.clear();
emit vm->tabsListChanged();
}
}


It seems like it has something to do with this. I found that the QQmlAdaptorModel is the model for the tabview...
It also seems that it tries to create the tabs from the tabmodel from the previous layout after the new layout became active....
Anyone can help me further?
Regards,

Jan

anda_skoa
15th December 2016, 17:35
Are those viewmanager instances available through out the program or do they get creates/deleted on demand?

Do you have any Q_INVOKABLE methods that return instances of QObject derived classes?

Cheers,
_

JanW
16th December 2016, 08:28
Hi,

they are available through the entire lifetime of the application (the tabs are stored per layout in a QList<std::shared_ptr>. I have one Q_INVOKABLE method that returns a pointer to the tab.



Q_INVOKABLE ViewManagerTabQMLInterface* getTab(int index);

//--------------------------------------------------------------------------------------
/// Returns the tab model from the given index.
//--------------------------------------------------------------------------------------

ViewManagerTabQMLInterface* ViewManagerQMLInterface::getTab(int index)
{
if(index >= 0 && index < (int)_tabsList.size())
{
return _tabsList[index].get();
}
return NULL;
}


I see that at one point the destructor of the ViewManagerTabQMLInterface is called after a QDeleteDefferedEvent (just reading from the call stack).



MeshingMaster.exe!ViewManagerTabQMLInterface::~Vie wManagerTabQMLInterface() Line 69 C++
[External Code]
Qt5Cored.dll!qDeleteInEventHandler(QObject * o) Line 4482 C++
> Qt5Cored.dll!QObject::event(QEvent * e) Line 1255 C++
Qt5Widgetsd.dll!QApplicationPrivate::notify_helper (QObject * receiver, QEvent * e) Line 3799 C++
Qt5Widgetsd.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3159 C++
Qt5Cored.dll!QCoreApplication::notifyInternal2(QOb ject * receiver, QEvent * event) Line 988 C++
Qt5Cored.dll!QCoreApplication::sendEvent(QObject * receiver, QEvent * event) Line 231 C++
Qt5Cored.dll!QCoreApplicationPrivate::sendPostedEv ents(QObject * receiver, int event_type, QThreadData * data) Line 1649 C++
Qt5Cored.dll!QEventDispatcherWin32::sendPostedEven ts() Line 1295 C++
qwindowsd.dll!QWindowsGuiEventDispatcher::sendPost edEvents() Line 82 C++
Qt5Cored.dll!qt_internal_proc(HWND__ * hwnd, unsigned int message, unsigned __int64 wp, __int64 lp) Line 445 C++
[External Code]
Qt5Cored.dll!QEventDispatcherWin32::processEvents( QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 845 C++
qwindowsd.dll!QWindowsGuiEventDispatcher::processE vents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 74 C++
Qt5Cored.dll!QEventLoop::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 135 C++
Qt5Cored.dll!QEventLoop::exec(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 210 C++
Qt5Cored.dll!QCoreApplication::exec() Line 1261 C++


Any idea?

anda_skoa
16th December 2016, 10:10
they are available through the entire lifetime of the application (the tabs are stored per layout in a QList<std::shared_ptr>. I have one Q_INVOKABLE method that returns a pointer to the tab.

Do those objects have a QObject parent?
Or, alternatively, have they been marked as owned by C++ using QQmlEngine::setObjectOwnership()?

Cheers,
_

JanW
16th December 2016, 11:01
Yes, they have a qobject parent, and yes, at one point they get deleted. I removed the passing of those objects via qml to my other class and now they stay alive.
Thanks you very much for the tips!!!!
Regards,

Jan