GC崩溃了QML-Application

时间:2016-11-18 13:09:20

标签: javascript qt garbage-collection qml qtquick2

  

不要害怕!这不是生产代码。它只是学习QML的新东西!我不寻求你不会做这样的事情 - 这样做。'我对QML的内部更感兴趣

考虑以下QML代码

import QtQuick 2.4
import QtQuick.Window 2.0

Window {
    id: root
    width: 800
    height: 600
    visible: true
    GridView {
        width: 800
        height: 200
        model: 4000
        flow: GridView.FlowTopToBottom

        delegate: Rectangle {
            id: myDelegate
            width: 100
            height: 100
            border.width: 1
            Column {
                anchors.fill: parent
                Text {
                    text: index
                    height: 20
                    width: parent.width
                }
                Item {
                    id: frame0
                    height: 20
                    width: parent.width
                }
                Item {
                    id: frame1
                    height: 20
                    width: parent.width
                }
            }

            Component.onCompleted: {
                // if (index % 100 === 0) gc()
                frame0.children = [myComp.createObject(myDelegate)]
                frame1.children = [myComp.createObject(null)]
                frame0.children[0].text = 'QML ' + index

                frame1.children[0].text = 'JS ' + index
            }
        }

        Component {
            id: myComp
            Text {
                anchors.centerIn: parent
                Component.onDestruction: console.log('Destroy ' + text)
            }
        }
    }
}

在使用动态ObjectCreation(JS)时,它在某种程度上说明了QML的MemoryManagement。 我有一个ListView,可以创建一些代表,让我浏览它们,按需创建新的代理。

技巧是:当创建新委托时,它使用JavaScript动态对象创建来创建文本对象的两个实例。

其中一个是代表的父级,另一个是null的父级,因此它的生命由JS-Engine决定。它应该是垃圾收集,一旦没有指针,指向它。

首先,我会将它们放在frameItem)中,以显示(设置可视父级)。作为代表,这些框架被销毁。 这将 - 正如预期的那样 - 破坏动态创建的对象,该对象也将委托作为父对象。另一个(应该)留给垃圾收集器来完成他的工作。

这就是它失败的地方 - 有时候应用程序会在GC启动之前崩溃,有时会崩溃,而GC正在尝试完成它的工作。

虽然文档没有推荐,但确实有助于手动调用GC(激活Component.onCompleted中注释掉的行。)

所以在我看来,GC高估了它的能力,并决定在已经迟到的时候开始。

这可能是什么原因?有没有办法告诉GC是否主动

  

再次:我不打算在我的代码中使用.createObject(null)创建动态对象。这是纯粹的好奇心。

1 个答案:

答案 0 :(得分:2)

  

这可能是什么原因?有没有办法告诉GC   mor主动?

原因是buggy qtquick object lifetime实施。在这一点上,它看起来不是一个JS的东西,而是一个qtquick的东西。它显然是doesn't abide to its own alleged rules - 例如,它会在仍在使用时删除具有父项的对象,从而导致硬崩溃。您不能指望引用计数也能正常工作。在许多采用动态的场景中可能会发生此行为,通常不会在琐碎和静态场景中显示。

如链接问题中所述,解决方案是使用手动对象生存期管理。使用一组新函数来创建和删除对象。

  • 创建时,你必须将对象传递给C ++端才能在其上调用QQmlEngine::setObjectOwnership(ojb, QQmlEngine::CppOwnership);,这基本上告诉qtquick"不要打扰尝试",幸运的是至少这可以按原样使用
  • 要进行销毁,您必须将对象传递给C ++端才能调用obj->deleteLater();

对我来说,这就是诀窍,我不会因为没有明显的原因而崩溃。使用自定义生命周期管理并远离库存功能。它给你保证,只要你需要它就会保持对象 ,但它也不会超出你想要的那个点,这是另一个问题,尽管不是那么严重。当然,这消除了使用JS的便利因素,因为你必须放弃自动生命周期管理,并且使用自己的代码更加勤奋和明确,但是你无法做很多事情。虽然这个漏洞几乎在一年前被报道并被认为是 critical ,但并没有对它做过任何一件事。因此,我认为,作为严重,因为它可能在其严重性中,在找到原因并修复它时更像是最低优先级