2013-04-14 1 views
2

Я использую 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; 
} 

Благодаря

ответ

4

Похоже, у вас есть "классические" проблемы с использованием QAbstractListModel на QML стороне. В вашем нерегулярномListWrapper есть метод «get», который возвращает объекты с собственностью JS (такой тип собственности по умолчанию используется для методов Q_INVOKABLE), и они будут мусором, собранным с JS-движком на стороне QML. Чтобы предотвратить это, вы должны изменить права собственности на объекты, прежде чем возвращать их в QML с помощью QDeclarativeEngine::setObjectOwnership. См. Пример в моем ответе here.

+0

Ну, спасибо! Я обновил OP, не могли бы вы посмотреть, будет ли измененный get (...) в порядке? Btw. почему сбор мусора на стороне QML причиняет ему боль? Спасибо – marmistrz

+1

Итак, обновленный код должен работать без сбоев, если вы не возвращаете объекты из методов Q_INVOKABLE в другое место. Но во время вставки будет намного проще настраивать право собственности, но не каждый раз, когда вы предоставляете объекты QML. –

+1

Причина сбоев в том, что когда JS уничтожит объекты, ваш ListWrapper не будет уведомлен об этом, и он будет содержать оборванные указатели. Затем, когда какой-либо другой объект будет их использовать (например, QML спросит вашего Wrapper для объектов с теми же индексами, которые он был ранее использован и уничтожен) и доступ к любому из его полей будет сбой –

 Смежные вопросы

  • Нет связанных вопросов^_^