Memory problem with QML data binding through C++



  • I tried to build two C++ classes and use QML to bind a data between the two classes. There seem to be a memory problem whenver the data is updated. Basically, I generate data from Class Foo1, and the data is binded in the qml to another variable from Foo2. In the qml, I have a button to call a function in Foo1 to update its data. Whenver the data is updated (button is clicked), the system memory used would keep increasing. I've tried to get the simpliest code that could replicate the problem as attached. Am I doing sth wrong here? Or is it a bug? Thanks in advance.

    Note that the larger the size of the data, the larger the memory used would increase with every update.

    Class Foo1 is a QObject and has a property testData which is a std::vector. It also has a loadData slot to generate/update the data. It looks like this:
    @class Foo1 : public QObject
    {
    Q_OBJECT
    Q_PROPERTY(std::vector<double> testData READ testData WRITE setTestData NOTIFY testDataChanged)

    public:
    explicit Foo1(QObject *parent = 0);
    std::vector<double> testData() const;
    void setTestData(std::vector<double> ask);
    private:
    std::vector<double> m_testData;

    signals:
    void testDataChanged();
    public slots:
    void loadData();
    };@
    @Foo1::Foo1(QObject *parent) :
    QObject(parent)
    {
    }
    std::vector<double> Foo1::testData() const
    {
    return m_testData;
    }
    void Foo1::setTestData(std::vector<double> testdata)
    {
    m_testData=testdata;
    emit testDataChanged();
    }

    void Foo1::loadData()
    {

    std::vector<double> testd(30000,0);
    setTestData(testd);
    

    }@

    Class Foo2 is a QDeclarativeItem. It has a property plotData which will be binded to testData from Foo1.
    @class Foo2 : public QDeclarativeItem
    {
    Q_OBJECT
    Q_PROPERTY(std::vector<double> plotData READ plotData WRITE setPlotData NOTIFY plotDataChanged)

    public:
    explicit Foo2(QDeclarativeItem *parent = 0);
    std::vector<double> plotData() const;
    void setPlotData(std::vector<double> plotdata);
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
    private:
    std::vector<double> m_plotData;

    signals:
    void plotDataChanged();

    public slots:

    };@
    @Foo2::Foo2(QDeclarativeItem *parent) :
    QDeclarativeItem(parent)
    {
    setFlag(QGraphicsItem::ItemHasNoContents, false);
    }

    std::vector<double> Foo2::plotData() const
    {
    return m_plotData;
    }

    void Foo2::setPlotData(std::vector<double> plotdata)
    {
    m_plotData=plotdata;
    emit plotDataChanged();
    update();
    }
    void Foo2::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
    {
    }@

    main.cpp is
    @ qmlRegisterType<Foo2>("Rec", 1, 0, "Rec");

    qRegisterMetaType<std::vector<double> >("std::vector<double>");
    
    QScopedPointer<QApplication> app(createApplication(argc, argv));
    QScopedPointer<QmlApplicationViewer> viewer(QmlApplicationViewer::create());
    
    viewer->rootContext()->setContextProperty("foo1",new Foo1);
    viewer->setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
    viewer->setMainQmlFile(QLatin1String("qml/testQML3/main.qml"&#41;&#41;;
    viewer->showExpanded(&#41;;
    
    return app->exec(&#41;;@
    

    mai.qml is
    @Rectangle {
    width: 360
    height: 360
    Item{
    width: 147
    height: 36

        Rec{
            id:testChart
            width:147
            height:36
            plotData: foo1.testData
        }
    }
    Rectangle {
        id: connect2
        x: 13
        y: 80
        width: 81
        height: 24
        radius: 5
        border.width: 3
        border.color: "#e0e0e0"
        smooth: true
        Text{
            anchors.fill: parent
            text: "Click"
        }
        MouseArea{
            anchors.fill:parent
    
            onClicked: foo1.loadData(&#41;
        }
    }
    

    }@



  • I'm not a C++ expert. But I doubt the line @viewer->rootContext()->setContextProperty("foo1",new Foo1);@ to be responsible for increase in memory consumption during each Mouse Click.

    By the way, how are you checking these memory consumption details. I'm always wondering about this method. Is is some kind of tool? Please suggest me.

    I have heard about Valgrind which can detect memory leaks. You may try that.



  • [quote author="raja26" date="1324401091"]I'm not a C++ expert. But I doubt the line @viewer->rootContext()->setContextProperty("foo1",new Foo1);@ to be responsible for increase in memory consumption during each Mouse Click.
    [/quote]

    It could be. I'm not an expert either. So I'm not sure about it. I did try to create foo1 as a qmlregistertype/import from qml. The same thing happened.

    I simply used resource monitor to check memory usage. You can see it keep increasing with each mouse click.

    I also tried Valgrind but it didnt seem to give any meaningful information in this case.



  • Does manually calling gc() (which triggers garbage collection) after foo1.loadData() make any difference?



  • [quote author="mbrasser" date="1324446619"]Does manually calling gc() (which triggers garbage collection) after foo1.loadData() make any difference?[/quote]

    That did the trick! Thanks! Where do you think the memory got leaky? In general, should I call gc() often when using QT? Thanks!

    EDIT: actually even calling gc() before loadData() worked. So I'm confused which caused this.



  • bq. Does manually calling gc() (which triggers garbage collection) after foo1.loadData() make any difference?

    Wait wait.. Am I in any Java forum??.. Does QML implements a GC?.. Please explain me. By the way, calling GC is usually a dirty way, being a C++ developer, I guess:P.

    bq. It could be. I’m not an expert either. So I’m not sure about it. I did try to create foo1 as a qmlregistertype/import from qml. The same thing happened.

    I didn't mean to import it to QML. This may look silly, but try this and post the reply here

    @
    Foo1 foo;
    viewer->rootContext()->setContextProperty("foo1",&foo);@



  • [quote author="raja26" date="1324483104"]
    I didn't mean to import it to QML. This may look silly, but try this and post the reply here

    @
    Foo1 foo;
    viewer->rootContext()->setContextProperty("foo1",&foo);@[/quote]
    Did that and it didnt help.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.