Я пытаюсь проверить QML, чтобы понять, как это работает с C++. У меня есть ClassA
и ClassB
- 2 похожих класса C++. Вот ClassA
. Все методы объясняются с их именами, поэтому я не буду размещать реализацию здесь.Управление памятью QML
class ClassB;
class ClassA : public QObject
{
Q_OBJECT
public:
explicit ClassA(QObject *parent = 0);
~ClassA();
Q_PROPERTY(ClassB* classB READ getClassB WRITE setClassB NOTIFY classBChanged)
ClassB* getClassB() const;
void setClassB(ClassB *classB);
signals:
void classBChanged();
private:
ClassB *m_classB;
};
ClassB
это то же самое, просто изменить все *lassA*
к *lassB*
и все *lassB*
к *lassA*
.
Тогда зарегистрироваться и классифицироваться в QML с
qmlRegisterType<ClassA>("testmodule.test",1,0,"ClassA");
qmlRegisterType<ClassB>("testmodule.test",1,0,"ClassB");
И в QML
кода на кнопке мыши создать оба объекта, как это:
onClicked: {
var comp = Qt.createComponent("TClassA.qml"); //TClassA.qml is
//a component of type
//ClassA
var ca = comp.createObject();
comp = Qt.createComponent("TClassB.qml");
var cb = comp.createObject();
ca.classB = cb;
cb.classA = ca;
parent.blockFromGC = ca;
}
И после того, что я называю сборщик мусора с gc()
. Я ожидал, что ca
заблокирован от удаления с parent.blockFromGC
и cb
заблокирован от удаления со ссылкой на ca
. Но сборщик мусора уничтожил cb
, а затем parent.blockFromGC.classB === null
.
Так что я второй MouseArea
с этим кодом:
onClicked: {
console.log(mouse.button)
// if (mouse.button == Qt.RightButton) {
// console.log(parent.vasya.classB)
// }
gc();
console.log(parent.blockFromGC.classB) //I use cb here
}
Так что, когда я нажимаю MouseArea
я получаю в консоли:
qml: 1 //Left button
qml: null //value of parent.blockFromGC.classB
classB destroyed: TQMLClassB(0x34960d0) //I have qDebug() in destructor
Так что мой объект cb
был разрушен.
Так что у меня этот вопрос:
1) Есть ли способ, как я могу зарегистрировать C++
типа как основного типа, так что я мог написать var ca = new ClassA()
вместо создания *.qml
файла, создание компонента и, наконец, создание объект?
2) Почему сборщик мусора уничтожил мой объект cb
и что мне следует сделать , чтобы этот объект не удалялся?
Более того! Если я раскомментирую эти прокомментированные строки
// if (mouse.button == Qt.RightButton) {
// console.log(parent.vasya.classB)
// }
Независимо от того, на какую кнопку нажимаю, объект больше не будет уничтожен.
qml: 1 //left button
qml: TQMLClassB(0x3df8e90) //object is alive
.....
qml: 2 //right button
qml: TQMLClassB(0x3df8e90) //before gc() - alive
qml: TQMLClassB(0x3df8e90) //after gc() - alive
3) Где можно прочитать о QML
управления памятью Подробно? Я считаю это поведение действительно странным.
Дополнение 1: Я сыграл в этой ситуации немного больше, и результаты были непредсказуемыми. Я обновил с 5.3 до Qt 5.4, и это поведение с удалением объекта прошло. Проблема в том, что поведение было настолько непредсказуемым, что тот факт, что я не могу воспроизвести это поведение в Qt 5.4, не означает, что проблема исправлена. Я попытаюсь посмотреть в отчетах об ошибках и исправлениях ошибок. Если я что-то найду, я отправлю его здесь. Если нет, я попытаюсь воспроизвести эту ситуацию в Qt 5.4 и опубликовать отчет.
Вы можете поместить декомпозицию 'ClassA' внутри' Компонента' и создать ее через 'var ca = thisComponent.createObject (parent)'. Что касается уничтожения объектов - можете ли вы убедиться, на каком этапе был вызван дескриптор? Как я знаю, объект может быть разрушен, если нет ссылок на него, поэтому вам нужно искать таким образом. – folibis
@folibis В режиме отладки эта проблема стала проблемой вероятности. Иногда это случалось, а иногда и нет. След не дал мне много информации. Все вызовы функций выполнялись, как и ожидалось, в общих библиотеках, а некоторые из них были скрыты. И все они имеют довольно обычные имена для функций, которые пытаются удалить и объект. В любом случае, прочитайте дополнение к сообщению и спасибо за советы, как это можно сделать без создания файла * .qml. – JustAnotherCurious