C++ QAbstractListModel崩溃

C++ QAbstractListModel崩溃,c++,qt,list,model,qml,C++,Qt,List,Model,Qml,我正在使用QAbstractListModel向QML ListView公开数据。QML SectionScroller与此一起使用,它使用get和data函数 滚动一段时间后,会发生崩溃。回溯是: Program received signal SIGILL, Illegal instruction. 0x0000cdcc in QBasicAtomicInt::ref ( this=0x35) at /usr/include/QtCore/qatomic_armv6.h:11

我正在使用QAbstractListModel向QML ListView公开数据。QML SectionScroller与此一起使用,它使用get和data函数

滚动一段时间后,会发生崩溃。回溯是:

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();
}
class-ListWrapper:public QAbstractListModel
{
Q_对象
Q_属性(QString langName读取getLangName通知langChanged)
Q_属性(整数计数读取行计数已更改)
Q_枚举(语言)
公众:
Q_可调用int rowCount(const QModelIndex&=QModelIndex())const{return db->count();}
Q_可调用QObject*get(int index)const{return db->at(index);}
QVariant数据(常量QModelIndex&index,int角色)常量;
枚举语言
{
英语=0,
德语=1
};
枚举角色
{
Form0Role=Qt::UserRole+1,
Form1Role,
Form2Role
};
不规则ListWrapper();
QString getLangName()常量{return langName;}
Q_可调用的void changeLang(语言l){beginResetModel();db=0;setLang(语言l);endResetModel();}
静态QMap插件;
信号:
void langChanged();
受保护的:
void setLang(语言);
QString-langName;
抽象列表*db;
};
QListWrapper::数据(常量QModelIndex&index,int角色)常量
{
如果(!index.isValid())返回QVariant();
int rowno=index.row();
qDebug()getForm1();
打破
案例表单2角色:
返回动词->getForm2();
打破
}
返回QVariant();
}
摘要清单:

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");
类抽象列表:公共QObject,公共QList
{
Q_对象
公众:
void IV(constchar*a,constchar*b,constchar*c){append(新动词(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_接口(AbstractUnderlineList,“com.marmistrz.Plugin.AbstractUnderlineList/1.0”);
你知道为什么会这样吗?谢谢

/编辑1:谢谢你的回复。这样行吗

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;
}
Q_可调用QObject*get(int索引)
{
QObject*item=db->at(索引);
QDeclarativeEngine::setObjectOwnership(项,QDeclarativeEngine::CppOwnership);
item->setParent(this);//我需要这样做吗?QList子级会清理它,对吗?
退货项目;
}

谢谢

使用QML端的
QAbstractListModel
时,您似乎遇到了一个“经典”问题。您的
unregularlistwrapper
具有
get
方法,该方法返回具有JS所有权的对象(这种所有权是
Q_可调用的
方法的默认所有权),它们将通过QML端的JS引擎进行垃圾收集。为了防止这种情况,您应该在将对象返回到QML之前更改对象的所有权。请参见我答案中的示例。

好的,谢谢!我更新了OP,你能看看修改后的get(…)是否合适吗?顺便问一下,为什么在QML端收集垃圾会对它造成如此大的伤害?谢谢,如果您不从其他地方的Q_可调用方法返回对象,更新后的代码应该不会崩溃。但是,在插入过程中设置一次所有权会更干净,但不是每次向QML提供对象时都会如此。崩溃的原因是,当JS将销毁对象时,ListWrapper不会得到通知,它将包含悬空指针。然后,当其他对象使用它们时(例如,QML将要求您的包装器使用它以前使用和销毁过的相同索引的对象),访问它的任何字段时,都会出现崩溃,就像我做了
int*a=new int;删除一条;cout@marmistrz是的,这就是你的情况。