Название: Утечка памяти в QtScript
Отправлено: akaMDA от Декабря 25, 2012, 16:18
Имеется несколько классов, обернутых для QtScript. Обернуты однотипно, вот пример одного из них #ifndef XMLITEMOBJECT_H #define XMLITEMOBJECT_H //////////////////////////////////////////////////////////////// #include <QtCore/QtCore> #include <QtXmlPatterns/QtXmlPatterns> #include <QtScript/QtScript> //////////////////////////////////////////////////////////////// class xmlItemObject : public QObject, public QScriptable { Q_OBJECT //////////////////////////////////////////////////////////////// public: xmlItemObject(QObject *_parent = NULL); //////////////////////////////////////////////////////////////// signals: //////////////////////////////////////////////////////////////// public slots: bool isNull(); bool isNode(); //////////////////////////////////////////////////////////////// };
#endif // XMLITEMOBJECT_H
#include "xmlitemobject.h" //////////////////////////////////////////////////////////////// Q_DECLARE_METATYPE(QXmlItem*) //////////////////////////////////////////////////////////////// xmlItemObject::xmlItemObject(QObject *_parent) : QObject(_parent) { } //////////////////////////////////////////////////////////////// bool xmlItemObject::isNull() { QXmlItem *tmp = qScriptValueToValue<QXmlItem*>(this->thisObject()); return tmp->isNull(); } //////////////////////////////////////////////////////////////// bool xmlItemObject::isNode() { QXmlItem *tmp = qScriptValueToValue<QXmlItem*>(this->thisObject()); return tmp->isNode(); } ////////////////////////////////////////////////////////////////
Вот класс, в котором создаются констукторы для дижка #ifndef JSOBJECT_H #define JSOBJECT_H //////////////////////////////////////////////////////////////// #include <QtCore/QtCore> #include <QtXml/QtXml> #include <QtXmlPatterns/QtXmlPatterns> #include <QtScript/QtScript>
#include "xmlqueryobject.h" #include "xmlitemobject.h" #include "xmlresultitemsobject.h" #include "dbobject.h" #include "sqlqueryobject.h" //////////////////////////////////////////////////////////////// class jsObject : public QObject { Q_OBJECT //////////////////////////////////////////////////////////////// QScriptEngine* jsEngine;
static QScriptValue newDbObject(QScriptContext *_context, QScriptEngine *_engine); static QScriptValue newXmlItemObject(QScriptContext *_context, QScriptEngine *_engine); static QScriptValue newXmlQueryObject(QScriptContext *_context, QScriptEngine *_engine); static QScriptValue newXmlResultItemsObject(QScriptContext *_context, QScriptEngine *_engine); //////////////////////////////////////////////////////////////// public: explicit jsObject(QScriptEngine* _jsEngine, QObject *_parent = 0); //////////////////////////////////////////////////////////////// signals: //////////////////////////////////////////////////////////////// public slots: //////////////////////////////////////////////////////////////// };
#endif // JSOBJECT_H
#include "jsobject.h" //////////////////////////////////////////////////////////////// Q_DECLARE_METATYPE(QSqlDatabase*) Q_DECLARE_METATYPE(QXmlItem*) Q_DECLARE_METATYPE(QXmlQuery*) Q_DECLARE_METATYPE(QXmlResultItems*) //////////////////////////////////////////////////////////////// jsObject::jsObject(QScriptEngine *_jsEngine, QObject *_parent) : QObject(_parent) { this->jsEngine = _jsEngine;
QScriptValue dbO(this->jsEngine->newQObject(new dbObject, QScriptEngine::ScriptOwnership)); this->jsEngine->setDefaultPrototype(qMetaTypeId<QSqlDatabase*>(), dbO); QScriptValue dbOConstructor = this->jsEngine->newFunction(newDbObject, dbO); this->jsEngine->globalObject().setProperty("dbObject", dbOConstructor);
QScriptValue xmlItemO(this->jsEngine->newQObject(new xmlItemObject, QScriptEngine::ScriptOwnership)); this->jsEngine->setDefaultPrototype(qMetaTypeId<QXmlItem*>(), xmlItemO); QScriptValue xmlItemOConstructor = this->jsEngine->newFunction(newXmlItemObject, xmlItemO); this->jsEngine->globalObject().setProperty("xmlItemObject", xmlItemOConstructor);
QScriptValue xmlQueryO(this->jsEngine->newQObject(new xmlQueryObject, QScriptEngine::ScriptOwnership)); this->jsEngine->setDefaultPrototype(qMetaTypeId<QXmlQuery*>(), xmlQueryO); QScriptValue xmlQueryOConstructor = this->jsEngine->newFunction(newXmlQueryObject, xmlQueryO); this->jsEngine->globalObject().setProperty("xmlQueryObject", xmlQueryOConstructor);
QScriptValue xmlResultItemsO(this->jsEngine->newQObject(new xmlResultItemsObject, QScriptEngine::ScriptOwnership)); this->jsEngine->setDefaultPrototype(qMetaTypeId<QXmlResultItems*>(), xmlResultItemsO); QScriptValue xmlResultItemsOConstructor = this->jsEngine->newFunction(newXmlResultItemsObject, xmlResultItemsO); this->jsEngine->globalObject().setProperty("xmlResultItemsObject", xmlResultItemsOConstructor);
} //////////////////////////////////////////////////////////////// QScriptValue jsObject::newDbObject(QScriptContext *_context, QScriptEngine *_engine) { QSqlDatabase* db = new QSqlDatabase(QSqlDatabase::addDatabase(qScriptValueToValue<QString>(_context->argument(0)), qScriptValueToValue<QString>(_context->argument(1)) )); db->setDatabaseName(qScriptValueToValue<QString>(_context->argument(2)));
return qScriptValueFromValue<QSqlDatabase*>(_engine, db); } //////////////////////////////////////////////////////////////// QScriptValue jsObject::newXmlQueryObject(QScriptContext *_context, QScriptEngine *_engine) { QXmlQuery* xmlQuery = new QXmlQuery;
return qScriptValueFromValue<QXmlQuery*>(_engine, xmlQuery); } //////////////////////////////////////////////////////////////// QScriptValue jsObject::newXmlItemObject(QScriptContext *_context, QScriptEngine *_engine) { QXmlItem* xmlItem = qScriptValueToValue<QXmlItem*>(_context->argument(0));
return qScriptValueFromValue<QXmlItem*>(_engine, xmlItem); } //////////////////////////////////////////////////////////////// QScriptValue jsObject::newXmlResultItemsObject(QScriptContext *_context, QScriptEngine *_engine) { QXmlResultItems* xmlResultItems = new QXmlResultItems;
return qScriptValueFromValue<QXmlResultItems*>(_engine, xmlResultItems); } //////////////////////////////////////////////////////////////// Вот класс с параметрами, передаваемыми в скрипт #ifndef WORKSCRIPTPARAM_H #define WORKSCRIPTPARAM_H //////////////////////////////////////////////////////////////// #include <QtCore/QtCore> #include <QtScript/QtScript> #include <QtSql/QtSql> #include <QtXmlPatterns/QtXmlPatterns>
#include "xmlqueryobject.h" #include "xmlresultitemsobject.h" #include "dbobject.h" //////////////////////////////////////////////////////////////// class workScriptParam : public QObject { Q_OBJECT //////////////////////////////////////////////////////////////// QString message; QString typeValue; QString actionValue; QXmlResultItems* itemsData; QXmlQuery* xmlQuery; QSqlDatabase* db; //////////////////////////////////////////////////////////////// public: explicit workScriptParam(const QString &_message, const QString &_typeValue, const QString &_actionValue, QXmlResultItems *_itemsData, QXmlQuery *_xmlQuery, QSqlDatabase *_db, QObject *_parent = NULL ); ~workScriptParam(); //////////////////////////////////////////////////////////////// signals: void sendMessageSignal(QString* _mess); //////////////////////////////////////////////////////////////// public slots: QString getMessage(); QString getTypeMessage(); QString getActionMessage(); QXmlQuery* getXmlQuery(); QXmlResultItems* getItemsData(); QSqlDatabase* getDb(); void sendMessage(QString _mess); //////////////////////////////////////////////////////////////// };
#endif // WORKSCRIPTPARAM_H
#include "workscriptparam.h" //////////////////////////////////////////////////////////////// workScriptParam::workScriptParam(const QString &_message, const QString &_typeValue, const QString &_actionValue, QXmlResultItems *_itemsData, QXmlQuery *_xmlQuery, QSqlDatabase *_db, QObject *_parent ) : QObject(_parent) { this->message = _message; this->typeValue = _typeValue; this->actionValue = _actionValue; this->itemsData = _itemsData; this->xmlQuery = _xmlQuery; this->db = _db; } //////////////////////////////////////////////////////////////// workScriptParam::~workScriptParam() { } //////////////////////////////////////////////////////////////// QString workScriptParam::getMessage() { return this->message; } //////////////////////////////////////////////////////////////// QString workScriptParam::getTypeMessage() { return this->typeValue; } //////////////////////////////////////////////////////////////// QString workScriptParam::getActionMessage() { return this->actionValue; } //////////////////////////////////////////////////////////////// QXmlQuery *workScriptParam::getXmlQuery() { return this->xmlQuery; } //////////////////////////////////////////////////////////////// QXmlResultItems *workScriptParam::getItemsData() { return this->itemsData; } //////////////////////////////////////////////////////////////// QSqlDatabase* workScriptParam::getDb() { return this->db; } //////////////////////////////////////////////////////////////// void workScriptParam::sendMessage(QString _mess) { QString* tmpMes = new QString(_mess);
emit this->sendMessageSignal(tmpMes); } //////////////////////////////////////////////////////////////// Вот скрипт if(param.getTypeMessage() === 'QUERY' && param.getActionMessage() === 'TASK') { var db = param.getDb();
var xmlQuery = param.getXmlQuery(); var itemsData = param.getItemsData(); var item = itemsData.next(); while(!item.isNull()) { if(item.isNode()) { xmlQuery.setFocus(item); xmlQuery.setQuery("./actionsTask/actionTask"); if(!xmlQuery.isValid()) { print('ERROR(('); return; }
var itemsActionTask = new xmlResultItemsObject(); xmlQuery.evaluateTo(itemsActionTask); var itemActionTask = itemsActionTask.next();
var actions = [];
while (!itemActionTask.isNull()) { if(itemActionTask.isNode()) { xmlQuery.setFocus(itemActionTask); xmlQuery.setQuery("./string()"); if(!xmlQuery.isValid()) { print('ERROR(='); return; } var action = xmlQuery.evaluateTo();
print(action); actions.push(action); }
itemActionTask = itemsActionTask.next(); }
print(actions);
} item = itemsData.next(); }
if(db.transaction()) { if(!db.commit()) { print('error commit()'); } } else { print('error transaction()');
if(!db.rollback()) { print('error rollback()'); } }
} Вот он вызывается workScriptParam *p = new workScriptParam(*_mess, typeValue, actionValue, itemsData, xmlQuery, &this->db );
this->connect(p, SIGNAL(sendMessageSignal(QString*)), this, SLOT(sendMessageSlot(QString*)));
QScriptEngine* jsEngine = new QScriptEngine; jsObject *jsO = new jsObject(jsEngine);
QFile file(this->pathWorkScript); file.open(QIODevice::ReadOnly);
QScriptValue param = jsEngine->newQObject(p, QScriptEngine::ScriptOwnership); jsEngine->globalObject().setProperty("param", param);
QScriptValue res = jsEngine->evaluate(file.readAll());
if(res.isError()) { output::printError(QString("Script \"%1\" is error %2").arg(this->pathWorkScript).arg(res.toString()).toStdWString().c_str(), __FILEW__, __LINE__); throw; }
file.close();
delete xmlQuery; delete itemsData; delete p;
delete jsO; delete jsEngine; Данный вызов происходит несколько 10-в раз в секунду, память постоянно растет. Что я не так делаю? Почему объекты не удаляются? Утечка именно в скрипте, потому что если его вызов убрать все нормально.
Название: Re: Утечка памяти в QtScript
Отправлено: carrygun от Декабря 26, 2012, 05:22
jsEngine->newQObject(p, QScriptEngine::ScriptOwnership); А QtOwnership не пробовал?
Название: Re: Утечка памяти в QtScript
Отправлено: akaMDA от Декабря 27, 2012, 10:08
Пробовал. В итоге всех манипуляций скрипт работает себе, но ужирается памятью в большом количестве. Можно как-то влиять на сборщик мусора QtScript?
Название: Re: Утечка памяти в QtScript
Отправлено: carrygun от Декабря 27, 2012, 10:15
Про сборщик тут: http://qt-project.org/doc/qt-4.8/scripting.html#controlling-qobject-ownership
Название: Re: Утечка памяти в QtScript
Отправлено: akaMDA от Декабря 27, 2012, 11:00
Да уже сам разобрался. Вызываю и все вроде норм. Только не очень понял void reportAdditionalMemoryCost ( int size ) по документации. Можно пояснить ее?
|