将带有Javascript数组的对象附加到QML ListModel会导致SEGFAULT

时间:2022-09-28 21:15:10

I am using QtQuick on Android.

我在Android上使用QtQuick。

I am trying to append a Javascript object with an array property to a ListModel.

我试图将具有数组属性的Javascript对象附加到ListModel。

I use LocalStorage to store this data.

我使用LocalStorage来存储这些数据。

The object I materialise from the database has this array property, and when I try and append that object to the ListModel I get a SEGFAULT. If I do not include an array in my object, or in fact if the array is empty, then it will successfully append to the ListModel and will not SEGFAULT.

我从数据库实现的对象具有此数组属性,当我尝试将该对象附加到ListModel时,我得到一个SEGFAULT。如果我没有在我的对象中包含一个数组,或者实际上如果数组为空,那么它将成功附加到ListModel而不会是SEGFAULT。

When I materialise the object from the database, I do this:

当我从数据库中实现对象时,我这样做:

var movie = {
    id: row.id,
    title: row.title,
    genres: ['a', 'b', 'c']
}

I'm creating a Javascript object and copying properties from the LocalStorage result-set object 'row'. For the sake of this issue, I just hard-code the array as you can see above. When this object is appended to the ListModel it SEGFAULTs.

我正在创建一个Javascript对象并从LocalStorage结果集对象'row'复制属性。为了解决这个问题,我只需要对上面的数组进行硬编码。当此对象附加到ListModel时,它就是SEGFAULTs。

If I remove the genres attribute completely, or even leave it empty as in [], it will not SEGFAULT when appended:

如果我完全删除了genres属性,或者甚至将它留在[]中,那么在附加时它不会是SEGFAULT:

var movie = {
    id: row.id,
    title: row.title,
    genres: []
}

Here is the stack trace:

这是堆栈跟踪:

0   ListModel::set(int, QV4::Referenced<QV4::Object>, QV8Engine*)   /home/linux/qt/Qt5.2.1/5.2.1/android_armv7/lib/libQt5Qml.so     0x7542b138  
1   ListModel::append(QV4::Referenced<QV4::Object>, QV8Engine*) /home/linux/qt/Qt5.2.1/5.2.1/android_armv7/lib/libQt5Qml.so     0x7542b40a  
2   ListModel::set(int, QV4::Referenced<QV4::Object>, QV8Engine*)   /home/linux/qt/Qt5.2.1/5.2.1/android_armv7/lib/libQt5Qml.so     0x7542b26c  
3   ListModel::append(QV4::Referenced<QV4::Object>, QV8Engine*) /home/linux/qt/Qt5.2.1/5.2.1/android_armv7/lib/libQt5Qml.so     0x7542b40a  
4   QQmlListModel::append(QQmlV4Function*)  /home/linux/qt/Qt5.2.1/5.2.1/android_armv7/lib/libQt5Qml.so     0x7542d21c  
5   QQmlListModel::qt_metacall(QMetaObject::Call, int, void**)  /home/linux/qt/Qt5.2.1/5.2.1/android_armv7/lib/libQt5Qml.so     0x754347ea  
6   QMetaObject::metacall(QObject*, QMetaObject::Call, int, void**) /home/linux/qt/Qt5.2.1/5.2.1/android_armv7/lib/libQt5Core.so        0x75054416  
7   QV4::QObjectMethod::callInternal(QV4::CallData*)    /home/linux/qt/Qt5.2.1/5.2.1/android_armv7/lib/libQt5Qml.so     0x753ac7c4  
8   QV4::FunctionObject::call(QV4::CallData*)   /home/linux/qt/Qt5.2.1/5.2.1/android_armv7/lib/libQt5Qml.so     0x7537ed5e  
9   QV4::__qmljs_call_property(QV4::ExecutionContext*, QV4::Referenced<QV4::String>, QV4::CallDataRef)  /home/linux/qt/Qt5.2.1/5.2.1/android_armv7/lib/libQt5Qml.so     0x75380962  
10  ??          0x7727c2e8  
11  ??          0x7727c2e8  

After building Qt with full debug symbols and single-stepping, the crash is here:

在使用完整的调试符号和单步执行构建Qt之后,崩溃就在这里:

void ListModel::set(int elementIndex, QV4::ObjectRef object, QV8Engine *eng)
{
    ListElement *e = elements[elementIndex];

    QV4::ExecutionEngine *v4 = object->engine(); <= SEGFAULT

When stepping through the code it seems when it encounters the Javascript array value for the genres property, the ListModel is attempting to create a sub-model and then it fails. This is called as a result of this piece of code also in the ListModel::set function:

当单步执行代码时,它似乎遇到了genres属性的Javascript数组值,ListModel正在尝试创建子模型然后失败。这也是ListModel :: set函数中的这段代码的结果:

} else if (propertyValue->asArrayObject()) {
    a = propertyValue;
    const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::List);
    if (r.type == ListLayout::Role::List) {
        ListModel *subModel = new ListModel(r.subLayout, 0, -1);

        int arrayLength = a->arrayLength();
        for (int j=0 ; j < arrayLength ; ++j) {
            o = a->getIndexed(j);
            subModel->append(o, eng); <= This leads to the nested 'set' call above that crashes
        }

So why is this failing?

那为什么会失败呢?

1 个解决方案

#1


2  

This fails because it is not supported to store non-object values such as literal strings or integers as property values in an array.

这会失败,因为不支持将非对象值(如文字字符串或整数)存储为数组中的属性值。

An array property can be stored, but only if each item in the array is an object, not a primitive or string literal.

可以存储数组属性,但前提是数组中的每个项都是对象,而不是基元或字符串文字。

This works:

var movie = {
    id: row.id,
    title: row.title,
    genres: [{name: 'a'}, {name: 'b'}, {name: 'c'}]
}

#1


2  

This fails because it is not supported to store non-object values such as literal strings or integers as property values in an array.

这会失败,因为不支持将非对象值(如文字字符串或整数)存储为数组中的属性值。

An array property can be stored, but only if each item in the array is an object, not a primitive or string literal.

可以存储数组属性,但前提是数组中的每个项都是对象,而不是基元或字符串文字。

This works:

var movie = {
    id: row.id,
    title: row.title,
    genres: [{name: 'a'}, {name: 'b'}, {name: 'c'}]
}