16,831
社区成员




根据Qt官方文档说的,可以在js中用createObject动态创建对象,并调用destroy()来销毁对象。
但我创建一堆对象,再把它们销毁后,内存并没有完全降低到创建前的状态(内存多了很多)。
比如下面这个Qml文件,它先创建50000个TextInput,6秒后销毁。
经多次测试,创建完内存是600~1200MB之间,销毁后内存是300~1000MB之间。
import QtQuick
import QtQuick.Controls
Window {
id: windows
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Component {
id: cp_test
TextInput {}
}
Timer {
running: true
repeat: false
interval: 6000
property var entitys: []
Component.onCompleted: {
for(let i = 0; i < 50000; ++i) { //动态创建5万个Qml对象
var entity = cp_test.createObject(windows)
entity.x = i*0.01
entity.y = 200
entity.text = "hello,world"
entitys.push(entity)
}
}
onTriggered: { // 6秒后
for(let obj of entitys)
obj.destroy() //动态销毁Qml对象
entitys = []
}
}
}
创建完有的时候600MB,有的时候1200MB。
600MB是创建完,完全不操作。销毁后是300MB。
1200MB是创建完,连续点击TextInput后的内存。销毁后,是900~1000MB。
我实在不明白为什么会这样,我怀疑Qml是否会预留内存?怎样才能完全释放这些内存?
在QML中调用obj.destroy()后内存未完全释放,可能的原因包括:
对象有父对象时销毁机制受限:当动态创建的对象(如Component.createObject(parent))指定了父对象后,destroy()可能无法彻底释放内存;而使用Component.createObject(null)(无父对象)则能更有效地释放内存。
信号连接或外部引用未正确处理:销毁对象时,未断开信号连接或清除外部引用(如JavaScript变量引用),导致垃圾回收机制无法回收资源,造成托管内存泄漏。
特定组件(如Shape)的内存泄漏问题:Qt QML的Shape组件在销毁时可能无法完全释放纹理资源或内部缓存,尤其在反复创建/销毁后内存累积显著。
QML内部预留内存或性能优化机制:QML运行时可能缓存对象资源以提升性能(如界面交互后的内存保留),导致销毁后内存未立即回落至初始状态。
事件订阅未及时清理:类似托管内存泄漏场景,对象事件被订阅后未注销,即使调用destroy(),引用仍被持有阻止完全释放。
为优化内存释放,建议:
优先使用无父对象方式创建动态对象(createObject(null))。
在销毁前手动断开所有信号连接并清除外部引用。
避免使用已知泄漏组件(如Shape),改用Canvas替代绘图需求。
监控内存使用并测试不同场景(如静态创建 vs 动态销毁)以确保资源回收。