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() { }
-
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 signalvoid 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.