Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QSGNode updatePaintNode() implementationo has memory leak?



  • I have created a linux application using QML. I am drawing zones on a video. the zones change colors, and appear or disappear depending on system side information. This data for zone color and position is provided by a variable: m_zoneList

    When I run my application for an extended period, I see the Mem used % start to grow. The more often I draw the zones, the faster the Mem used % grows. Could someone please take a look at this and see if I made a dumb mistake?

    QSGNode *Zones::updatePaintNode(QSGNode * oldNode, UpdatePaintNodeData *)
    {
    #if 1
     QSGNode *root = static_cast<QSGNode *>(oldNode);
     if(!root) {
         root = new QSGNode;
     }
    
     root->removeAllChildNodes();
     int sz = m_zoneList.size();
     QColor fgnd;
     QColor bgnd;
    
     if(sz > 0)
     {
         int i = 0;
         while(i < sz)	// paint the contrast zone (bgnd color) then the normla zone (fgnd color)
         {
            //i = 0;
            QVariantList zList = m_zoneList.at(i).toList();
            fgnd.setNamedColor(zList.at(4).toString());
            bgnd.setNamedColor(zList.at(5).toString());
    	QPointF xy1 = zList.at(0).toPointF();
    	QPointF xy2 = zList.at(1).toPointF();
    	QPointF xy3 = zList.at(2).toPointF();
    	QPointF xy4 = zList.at(3).toPointF();
            //QPointF points[4] = {xy1, xy2, xy3, xy4};
    
            QSGFlatColorMaterial *cm = new QSGFlatColorMaterial;
            cm->setColor(bgnd);
    
            QSGGeometry *geoCZone = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4);
            geoCZone->setLineWidth(6);
            geoCZone->setDrawingMode(QSGGeometry::DrawLineLoop);
            geoCZone->vertexDataAsPoint2D()[0].set(xy1.x(),xy1.y());
            geoCZone->vertexDataAsPoint2D()[1].set(xy2.x(),xy2.y());
            geoCZone->vertexDataAsPoint2D()[2].set(xy3.x(),xy3.y());
            geoCZone->vertexDataAsPoint2D()[3].set(xy4.x(),xy4.y());
    
            QSGGeometryNode *contrastZone = new QSGGeometryNode;
            contrastZone->setGeometry(geoCZone);
            contrastZone->setMaterial(cm);
            contrastZone->setFlag(QSGNode::OwnsGeometry);
            contrastZone->setFlag(QSGNode::OwnsMaterial);
             	
            QSGGeometry *geoZn = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4);
            geoZn->setLineWidth(3);
            geoZn->setDrawingMode(QSGGeometry::DrawLineLoop);
            geoZn->vertexDataAsPoint2D()[0].set(xy1.x(),xy1.y());
            geoZn->vertexDataAsPoint2D()[1].set(xy2.x(),xy2.y());
            geoZn->vertexDataAsPoint2D()[2].set(xy3.x(),xy3.y());
            geoZn->vertexDataAsPoint2D()[3].set(xy4.x(),xy4.y());
    	
            QSGFlatColorMaterial *z = new QSGFlatColorMaterial;
            z->setColor(fgnd);
    
            QSGGeometryNode *zone = new QSGGeometryNode; 	
            zone->setGeometry(geoZn);   
            zone->setMaterial(z);	
    	zone->setFlag(QSGNode::OwnsGeometry);
            zone->setFlag(QSGNode::OwnsMaterial);
    
            root->appendChildNode(contrastZone);
            root->appendChildNode(zone);
    	i++;
         }
     } 
    return root;
    #endif
    }
    

  • Moderators

    @mxyn said in QSGNode updatePaintNode() implementationo has memory leak?:

    @sierdzio Good point. But because I use setFlag(QSGNode::OwnsGeometry) and setFlag(QSGNODE::OwnsMaterial), this should not be an issue. By setting these flags, the objects should be deleted when the child node is deleted.

    Yes, deleted. Not removed. So if you do:

    delete root;
    

    It will delete all child nodes.

    Anyway, I'm only guessing this based on the fact that documentation does not mention what happens to a node when it's owned and removed. Perhaps I'm wrong. Check with address sanitizer to be sure.


  • Moderators

    removeAllChildNodes() does not delete the objects. So you keep creating new nodes with every run of updatePaintNode().



  • @sierdzio Good point. But because I use setFlag(QSGNode::OwnsGeometry) and setFlag(QSGNODE::OwnsMaterial), this should not be an issue. By setting these flags, the objects should be deleted when the child node is deleted. At least, I think that's what the documentation is saying.

    https://doc.qt.io/qt-5/qsgnode.html#Flag-enum

    https://stackoverflow.com/questions/46394155/how-to-use-qsggeometrynode-without-causing-a-memory-leak-and-ensure-correct-clea


  • Moderators

    @mxyn said in QSGNode updatePaintNode() implementationo has memory leak?:

    @sierdzio Good point. But because I use setFlag(QSGNode::OwnsGeometry) and setFlag(QSGNODE::OwnsMaterial), this should not be an issue. By setting these flags, the objects should be deleted when the child node is deleted.

    Yes, deleted. Not removed. So if you do:

    delete root;
    

    It will delete all child nodes.

    Anyway, I'm only guessing this based on the fact that documentation does not mention what happens to a node when it's owned and removed. Perhaps I'm wrong. Check with address sanitizer to be sure.



  • @sierdzio Thank you! I tried your suggestion and it solved my problem. I wish the documentation was more explicit about needing to delete the nodes!


  • Moderators

    @mxyn said in QSGNode updatePaintNode() implementationo has memory leak?:

    I wish the documentation was more explicit about needing to delete the nodes!

    If you have time, please open a suggestion on Qt bugtracker and submit a patch for the documentation.


Log in to reply