Я использую QAbstractListModel для предоставления данных в QML ListView. QML SectionScroller используется рядом с этим, который использует функции get и data.QAbstractListModel сбой
После некоторого времени прокрутки произошел сбой. Трассировку является:
Program received signal SIGILL, Illegal instruction.
0x0000cdcc in QBasicAtomicInt::ref (
this=0x35)
at /usr/include/QtCore/qatomic_armv6.h:119
119 /usr/include/QtCore/qatomic_armv6.h: No such file or directory.
in /usr/include/QtCore/qatomic_armv6.h
(gdb) bt
#0 0x0000cdcc in QBasicAtomicInt::ref (
this=0x35)
at /usr/include/QtCore/qatomic_armv6.h:119
#1 0x0000f4e8 in QString (
this=0xbebf1a5c, other=...)
at /usr/include/QtCore/qstring.h:729
#2 [address] in IrregularVerb::getForm0
(this=0x92e428) at IrregularVerb.h:16
#3 0x0000e29c in IrregularListWrapper::data (this=0x92dd20, index=..., role=33)
at IrregularListWrapper.cpp:37
#4 0x4010e9c6 in ??()
from /usr/lib/libQtDeclarative.so.4
#5 0x4010e9c6 in ??()
from /usr/lib/libQtDeclarative.so.4
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
На другом устройстве (Первый N900, второй N950) Цепочка вызовов аналогично. Это SIGSEGV вместо SIGILL, но задняя сторона идентична. Я заметил однажды ситутацию, когда некоторые поля стали пустыми в момент аварии. (те, которые используют getForm0 и getForm1)
Когда я добавил дополнительную привязку к возвращенному значению, авария произошла при назначении.
Некоторые важные код:
Элемент:
class IrregularVerb : public QObject
{
Q_OBJECT
Q_PROPERTY(QString form0 READ getForm0 CONSTANT)
Q_PROPERTY(QString form1 READ getForm1 CONSTANT)
Q_PROPERTY(QString form2 READ getForm2 CONSTANT)
public:
QString forms[3];
QString getForm0() const { return forms[0]; }
QString getForm1() const { return forms[1]; }
QString getForm2() const { return forms[2]; }
IrregularVerb(QString a, QString b, QString c) { forms[0] = a; forms[1] = b; forms[2] = c; }
};
Модель:
class IrregularListWrapper : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(QString langName READ getLangName NOTIFY langChanged)
Q_PROPERTY(int count READ rowCount NOTIFY langChanged)
Q_ENUMS(Language)
public:
Q_INVOKABLE int rowCount(const QModelIndex& = QModelIndex()) const { return db->count(); }
Q_INVOKABLE QObject* get(int index) const {return db->at(index);}
QVariant data(const QModelIndex &index, int role) const;
enum Language
{
English = 0,
German = 1
};
enum IrregularVerbRoles
{
Form0Role = Qt::UserRole + 1,
Form1Role,
Form2Role
};
IrregularListWrapper();
QString getLangName() const { return langName; }
Q_INVOKABLE void changeLang(Language l) { beginResetModel(); db = 0; setLang(l); endResetModel(); }
static QMap<Language, QString> plugins;
signals:
void langChanged();
protected:
void setLang(Language);
QString langName;
AbstractIrregularList * db;
};
QVariant IrregularListWrapper::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) return QVariant();
int rowno = index.row();
qDebug() << "Row is " << index.row() << flush;
const IrregularVerb* verb = db->at(index.row());
switch (role)
{
case Form0Role:
return verb->getForm0();
break;
case Form1Role:
return verb->getForm1();
break;
case Form2Role:
return verb->getForm2();
break;
}
return QVariant();
}
AbstractIrregularList:
class AbstractIrregularList : public QObject, public QList<IrregularVerb*>
{
Q_OBJECT
public:
void IV(const char* a, const char* b, const char* c) { append (new IrregularVerb(a, b, c)); }
void IV(const char *a, const char *b) { IV(a, b, b); }
void IV(const char *a) { IV(a,a,a); }
};
Q_DECLARE_INTERFACE(AbstractIrregularList, "com.marmistrz.Plugin.AbstractIrregularList/1.0");
У вас есть идея, почему это происходит? Благодаря!
/edit1: Спасибо за ваш ответ. Это будет нормально?
Q_INVOKABLE QObject* get(int index)
{
QObject* item = db->at(index);
QDeclarativeEngine::setObjectOwnership(item, QDeclarativeEngine::CppOwnership);
item->setParent(this); // do I need to do this? An QList<QObject*>-child would clean it, right?
return item;
}
Благодаря
Ну, спасибо! Я обновил OP, не могли бы вы посмотреть, будет ли измененный get (...) в порядке? Btw. почему сбор мусора на стороне QML причиняет ему боль? Спасибо – marmistrz
Итак, обновленный код должен работать без сбоев, если вы не возвращаете объекты из методов Q_INVOKABLE в другое место. Но во время вставки будет намного проще настраивать право собственности, но не каждый раз, когда вы предоставляете объекты QML. –
Причина сбоев в том, что когда JS уничтожит объекты, ваш ListWrapper не будет уведомлен об этом, и он будет содержать оборванные указатели. Затем, когда какой-либо другой объект будет их использовать (например, QML спросит вашего Wrapper для объектов с теми же индексами, которые он был ранее использован и уничтожен) и доступ к любому из его полей будет сбой –