memory leak of SetStyleSheet of QWidget?



  • It maybe memory leak at styleSheetCaches of widgets/styles/qstylesheetstyle.cpp.

    I found that if I use setStyleSheet to set stylesheet to widget, when deleting widget, styleSheetCaches is not remove for that widget pointer.

    The sample code below can reproduce the memory leak.
    Due to too simple code(eg, not using board image in stylesheet and signalmapper), memory leak is too small. It also can see count of styleSheetCache and styleRulesCache of styleSheetCaches is increasing.

    The test is done by following step:
    1.In project, new a button.
    2.Counting the click of button, first is 0.
    3.even click is to new myQFrame.
    4.odd click is to delete myQFrame created previously.

    Question:
    1.Is it a memory leak?
    2.How to avoid? because in my project, I have a more complicate custom qframe class, and the memory reduce every time creating and deleting.

    //myqframe.h
    #ifndef MY_QFRAME_H
    #define MY_QFRAME_H
    
    #include <QFrame>
    #include <QWidget>
    #include <QObject>
    
    class MyQFrame : public QFrame
    {
        Q_OBJECT
    
    public:
        explicit MyQFrame(QWidget *parent = NULL);
        ~MyQFrame();    
    };
    
    #endif // MY_QFRAME_H
    
    
    //myqframe.cpp
    #include <QDateTime>
    #include <QPushButton>
    #include "myqframe.h"
    
    MyQFrame::MyQFrame(QWidget *parent)
        : QFrame(parent)
    {    
        setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
        setAttribute(Qt::WA_DeleteOnClose);
    
        QRect m_Rect;
        m_Rect.setRect(0, 0, 300, 200);
                
        if (parent != NULL)
        {
            QPoint pt = parent->rect().center();
            m_Rect.moveCenter(pt);
            m_Rect.moveTop(parent->rect().bottom());
            m_Rect.moveCenter(parent->mapToGlobal(m_Rect.center()));
        }
        setGeometry(m_Rect);
    
        setStyleSheet(QString("QFrame {border: 3px solid black; background-color: %1}").arg("rgb(20, 20, 20)"));
    
        QDateTime datetime = QDateTime::currentDateTime();
        qsrand(datetime.toTime_t());
    
        for (int i=0; i<40; i++)
        {
            QPushButton *btn = new QPushButton(QString("%1").arg(i), this);
    
            QString strColorNor = QString("rgb(%1, %1, %1)").arg(qrand()%255);
            QString strColorPress = QString("rgb(%1, %1, %1)").arg(qrand()%255);
            QString strColorFocus = QString("rgb(%1, %1, %1)").arg(qrand()%255);
            QString strColorFocusPress = QString("rgb(%1, %1, %1)").arg(qrand()%255);
            
            QString strStyle = QString("QPushButton{Color: %1;}").arg(strColorNor);
            strStyle.append(QString("QPushButton:pressed{Color: %1;}").arg(strColorPress));
            strStyle.append(QString("QPushButton:focus{Color: %1;}").arg(strColorFocus));
            strStyle.append(QString("QPushButton:focus:pressed{Color: %1;}").arg(strColorFocusPress));
    
            btn->setStyleSheet(strStyle);
            btn->setObjectName(QString("%1").arg(i));
        }
    }
    
    MyQFrame::~MyQFrame()
    {
    
    }
    


  • @Wujh
    add the signal void deleteButtons(); to your MyFrame and add the following connect to your loop:

    for (int i=0; i<40; i++)
        {
            QPushButton *btn = new QPushButton(QString("%1").arg(i), this);
            connect(this, &MyQFrame::deleteButtons,btn, &QPushButton::deleteLater);
    
            QString strColorNor = QString("rgb(%1, %1, %1)").arg(qrand()%255);
            QString strColorPress = QString("rgb(%1, %1, %1)").arg(qrand()%255);
            QString strColorFocus = QString("rgb(%1, %1, %1)").arg(qrand()%255);
            QString strColorFocusPress = QString("rgb(%1, %1, %1)").arg(qrand()%255);
            
            QString strStyle = QString("QPushButton{Color: %1;}").arg(strColorNor);
            strStyle.append(QString("QPushButton:pressed{Color: %1;}").arg(strColorPress));
            strStyle.append(QString("QPushButton:focus{Color: %1;}").arg(strColorFocus));
            strStyle.append(QString("QPushButton:focus:pressed{Color: %1;}").arg(strColorFocusPress));
    
            btn->setStyleSheet(strStyle);
            btn->setObjectName(QString("%1").arg(i));
        }
    

    emit the signal upon destruction:

    MyQFrame::~MyQFrame()
    {
        emit deleteButtons();
    }
    

    should solve the memory issue.



  • Why should call QPushButton::deleteLater?

    All QPushButtons are children of QFrame, and will be destroyed automaticly while QFrame deleted.



  • @Wujh oh, I'm sry, I overread that one, you're right, they have a parent and should be automatically deleted on destructon of QFrame.

    My bad, sry



  • After the butttons deleted, there is still some cache in styleSheetCache and styleRulesCache of styleSheetCaches corresponding to button pointers.

    But I do not know how to let qt delete them.

    Should I add a unpolish() at ~QWidget?


Log in to reply
 

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