Russian Qt Forum
Ноябрь 22, 2024, 05:33 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Утечка памяти в QtScript  (Прочитано 5082 раз)
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-в раз в секунду, память постоянно растет. Что я не так делаю? Почему объекты не удаляются? Утечка именно в скрипте, потому что если его вызов убрать все нормально.
Записан
carrygun
Гость
« Ответ #1 : Декабрь 26, 2012, 05:22 »

Код:
jsEngine->newQObject(p, QScriptEngine::ScriptOwnership);
А QtOwnership не пробовал?
Записан
akaMDA
Гость
« Ответ #2 : Декабрь 27, 2012, 10:08 »

Пробовал. В итоге всех манипуляций скрипт работает себе, но ужирается памятью в большом количестве. Можно как-то влиять на сборщик мусора QtScript?
Записан
carrygun
Гость
« Ответ #3 : Декабрь 27, 2012, 10:15 »

Про сборщик тут:
http://qt-project.org/doc/qt-4.8/scripting.html#controlling-qobject-ownership
Записан
akaMDA
Гость
« Ответ #4 : Декабрь 27, 2012, 11:00 »

Да уже сам разобрался. Вызываю
Код:
void	collectGarbage () 
и все вроде норм. Только не очень понял
Код:
 void	reportAdditionalMemoryCost ( int size )
по документации. Можно пояснить ее?
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.049 секунд. Запросов: 20.