Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ QQmlListProperty不稳定崩溃,所有权转移到JavaScript_C++_Qml_Qt5_Undefined Behavior_Qqmllistproperty - Fatal编程技术网

C++ QQmlListProperty不稳定崩溃,所有权转移到JavaScript

C++ QQmlListProperty不稳定崩溃,所有权转移到JavaScript,c++,qml,qt5,undefined-behavior,qqmllistproperty,C++,Qml,Qt5,Undefined Behavior,Qqmllistproperty,我在Qt5(5.8,ArchLinux)和QML上遇到了一些严重的鼻恶魔。基本上,代码公开了一个qqmlistproperty,其成员是动态创建的,并将其所有权转移到JavaScript。当itemChanged()信号被发出数千次(在我的实际代码中,只有几次就足够了)时,程序就会出错 根据Valgrind+GDB,看起来“A”被QObject::event释放,然后被QML读取,从而导致SEGFULT 奇怪的是,即使将变量“game”的名称更改为其他名称,也会改变我必须单击按钮使程序崩溃的次数

我在Qt5(5.8,ArchLinux)和QML上遇到了一些严重的鼻恶魔。基本上,代码公开了一个qqmlistproperty,其成员是动态创建的,并将其所有权转移到JavaScript。当itemChanged()信号被发出数千次(在我的实际代码中,只有几次就足够了)时,程序就会出错

根据Valgrind+GDB,看起来“A”被QObject::event释放,然后被QML读取,从而导致SEGFULT

奇怪的是,即使将变量“game”的名称更改为其他名称,也会改变我必须单击按钮使程序崩溃的次数。删除转发器或矩形,或者对矩形的颜色使用不同的表达式,都会影响程序是否崩溃。而且,当所有权没有转移到JS时,根本就没有问题。不幸的是,这也会导致内存泄漏,因为没有任何东西可以释放“A”对象

由于这些细节,我相信代码中有未定义的行为,但我不知道在哪里

这是我能创建的最短示例:

main.cpp:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QObject>
#include <QQmlListProperty>

template <typename T>
T* make_js() {
    T* t = new T();
    QQmlEngine::setObjectOwnership(t, QQmlEngine::JavaScriptOwnership);
    return t;
}

class A: public QObject {
    Q_OBJECT
    Q_PROPERTY(int id READ id CONSTANT)
public:
    int id() const {return 1;}
};

class B: public QObject {
    Q_OBJECT
    Q_PROPERTY(A* item READ item NOTIFY itemChanged)
    Q_PROPERTY(QQmlListProperty<A> list READ list CONSTANT)
public:

    A *item() const { return make_js<A>(); }

    Q_INVOKABLE void change() { emit itemChanged(); }

    QQmlListProperty<A> list() {
        return QQmlListProperty<A>(
            this, nullptr,
            [](QQmlListProperty<A> *) {return 1;},
            [](QQmlListProperty<A> *, int ) {return make_js<A>();});
    }
signals:
    void itemChanged();
};

#include "main.moc"

int main(int argc, char *argv[]) {
    QGuiApplication a(argc, argv);

    B* game = new B();

    QQmlApplicationEngine engine;

    qmlRegisterType<B>("example", 1, 0, "B");
    qmlRegisterType<A>("example", 1, 0, "A");
    engine.rootContext()->setContextProperty("thing", game);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    a.exec();

    delete game;
    return 0;
}
#包括
#包括
#包括
#包括
#包括
模板
T*make_js(){
T*T=新的T();
QQmlEngine::setObjectOwnership(t,QQmlEngine::JavaScriptOwnership);
返回t;
}
A类:公共质量对象{
Q_对象
Q_属性(int id READ id常量)
公众:
int id()常量{return 1;}
};
B类:公共质量对象{
Q_对象
Q_属性(A*项读取项通知项更改)
Q_属性(qqmlistproperty list READ list常量)
公众:
A*item()常量{return make_js();}
Q_可调用的void change(){emit itemChanged();}
QQmlListProperty列表(){
返回qqmlistproperty(
这个,nullptr,
[](qqmlistproperty*){return 1;},
[](qqmlistproperty*,int){return make_js();});
}
信号:
void itemChanged();
};
#包括“main.moc”
int main(int argc,char*argv[]){
QGUI应用程序a(argc、argv);
B*游戏=新的B();
qqmlaplicationengine;
qmlRegisterType(“示例”,1,0,“B”);
qmlRegisterType(“示例”,1,0,“A”);
engine.rootContext()->setContextProperty(“东西”,游戏);
engine.load(QUrl(QStringLiteral(“qrc:/main.qml”));
a、 exec();
删除游戏;
返回0;
}
main.qml:

import QtQuick 2.0
import QtQuick.Layouts 1.0
import QtQuick.Window 2.0
import QtQuick.Controls 2.0
import example 1.0

Window {
    visible: true
    width: 1280
    height: 800
    title: qsTr("Example")

    ColumnLayout {
        anchors.fill: parent

        Repeater {
            model: thing.list

            Rectangle {
                color: thing.item.id === 1 ? "red" : "blue"
            }
        }

        Item {
            Layout.fillWidth: true
            Layout.fillHeight: true

            Button {
                text: "Click me a bunch of times to crash!"
                anchors.fill: parent
                onClicked: {for(var i=0;i<1000;++i) thing.change();}
            }
        }
    }
}
导入QtQuick 2.0
导入QtQuick.Layouts 1.0
导入QtQuick.Window 2.0
导入QtQuick.Controls 2.0
导入示例1.0
窗口{
可见:正确
宽度:1280
身高:800
标题:qsTr(“示例”)
列布局{
锚定。填充:父级
中继器{
型号:thing.list
长方形{
颜色:thing.item.id==1?“红色”:“蓝色”
}
}
项目{
Layout.fillWidth:true
Layout.fillHeight:true
钮扣{
文字:“点击我几次就崩溃了!”
锚定。填充:父级
onClicked:{for(var i=0;i
Q_PROPERTY(QQmlListProperty<A> list READ list CONSTANT)
Q_PROPERTY(QQmlListProperty<A> list READ list NOTIFY listChanged)