Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Memory problem with QML data binding through C++
Forum Updated to NodeBB v4.3 + New Features

Memory problem with QML data binding through C++

Scheduled Pinned Locked Moved QML and Qt Quick
7 Posts 3 Posters 4.4k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    dodoei
    wrote on 17 Dec 2011, 06:02 last edited by
    #1

    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;
        }
    }
    

    }@

    1 Reply Last reply
    0
    • R Offline
      R Offline
      raja26
      wrote on 20 Dec 2011, 17:11 last edited by
      #2

      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.

      1 Reply Last reply
      0
      • D Offline
        D Offline
        dodoei
        wrote on 20 Dec 2011, 19:03 last edited by
        #3

        [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.

        1 Reply Last reply
        0
        • M Offline
          M Offline
          mbrasser
          wrote on 21 Dec 2011, 05:50 last edited by
          #4

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

          1 Reply Last reply
          0
          • D Offline
            D Offline
            dodoei
            wrote on 21 Dec 2011, 14:18 last edited by
            #5

            [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.

            1 Reply Last reply
            0
            • R Offline
              R Offline
              raja26
              wrote on 21 Dec 2011, 15:58 last edited by
              #6

              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);@

              1 Reply Last reply
              0
              • D Offline
                D Offline
                dodoei
                wrote on 22 Dec 2011, 02:13 last edited by
                #7

                [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.

                1 Reply Last reply
                0

                1/7

                17 Dec 2011, 06:02

                • Login

                • Login or register to search.
                1 out of 7
                • First post
                  1/7
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved