Can I instantiate new objects in QObject constructors?
-
wrote on 27 Jul 2022, 22:10 last edited by
Hi,
In my current project, I'm having a main
QWidget
which has aQTableView
as attribute and several buttons. When I run valgrind (memcheck), it complains about some memory here and there, which I outlined. BothTableView
andQtModel
inherit from Qt objects (QTableView
andQAbstractTableModel
respectively), withQ_OBJECT
in the class definition for both as well (h
files at the bottom).My understanding is that they're supposed to be cleaned up when the main widget is closed but there seems to be lingering memory, why?
I'm using it like that (abridged):
.h
file:class View : public QWidget { Q_OBJECT public: explicit View(QWidget *parent = nullptr); void setModel(QtModel *model); void connectToModel(); void pickFirstPlayer(); QLabel *createLabel(const QString &str); private: TableView *m_table = nullptr; // A subclass of QTableView QtModel *m_model = nullptr; QGridLayout *layout; QLCDNumber *redVictoryPoints; QLCDNumber *blackVictoryPoints; QLCDNumber *turns; QLabel *gameState = new QLabel("Pick a player!");
.cpp
file:View::View(QWidget *parent) : QWidget{parent} { layout = new QGridLayout; setLayout(layout); m_table = new TableView; // OFFENDING CODE? // show useful data and set items within layout redVictoryPoints = new QLCDNumber(2); blackVictoryPoints = new QLCDNumber(2); turns = new QLCDNumber(1); turns->setMaximumHeight(35); layout->addWidget( m_table, 0, 0, 9, 9); // 9 x 9 grid because there are 9 buttons per stack and 9 stacks layout->addWidget(createLabel(tr("TURNS")), 10, 0); layout->addWidget(turns, 10, 1); layout->addWidget(createLabel(tr("RED VICTORY POINTS")), 10, 3); layout->addWidget(redVictoryPoints, 10, 4); layout->addWidget(createLabel(tr("BLACK VICTORY POINTS")), 10, 6); layout->addWidget(blackVictoryPoints, 10, 7); layout->addWidget(createLabel(tr("GAME STATE")), 0, 10); layout->addWidget(gameState, 1, 10); gameState->setAlignment(Qt::AlignHCenter | Qt::AlignBottom); // --- Add the game and model ---// Game *g{new Game}; m_model = new QtModel; // OFFENDING CODE? m_model->setGame(g); setModel(m_model); connectToModel();
N.B: headers
QtModel.h
:#ifndef QTMODEL_H #define QTMODEL_H #include "game.h" #include <QAbstractTableModel> class QtModel : public QAbstractTableModel { Q_OBJECT public: explicit QtModel(QObject *parent = nullptr); // Header data QVariant headerData(int section, Qt::Orientation orientation, int role) const override; // Basic functionality: int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; void setGame(Game *game); Game *getGame(); void setState(Game::GameState); public slots: void moveStacksOnColumnClicked(const QModelIndex &idx); void replay(); private: Game *m_game = nullptr; signals: void turnChanged(int turns); void stateChanged(Game::GameState); void redTally(int); void blackTally(int); void roundTally(int, int); void endGame(int, int); }; #endif // QTMODEL_H
TableView.h
:#ifndef TABLEVIEW_H #define TABLEVIEW_H #include <QTableView> class TableView : public QTableView { Q_OBJECT public: TableView(); }; #endif // TABLEVIEW_H
-
wrote on 28 Jul 2022, 00:48 last edited by
When I run valgrind (memcheck), it complains about some memory here and there, which I outlined.
Where?
Child QObjects are deleted when the parent is deleted. QWidget::close() does not delete the object under default conditions, although it can.
The TableView object allocated on the line marked "OFFENDING CODE" is unparented until a few lines later when you add it to the layout, which has the effect of setting its parent for you. This memory will be freed when the parent object is (same true for the QLCDNumber objects).
The model object marked "OFFENDING CODE" is unparented and may stay that way depending on what View::setModel() is doing.
-
When I run valgrind (memcheck), it complains about some memory here and there, which I outlined.
Where?
Child QObjects are deleted when the parent is deleted. QWidget::close() does not delete the object under default conditions, although it can.
The TableView object allocated on the line marked "OFFENDING CODE" is unparented until a few lines later when you add it to the layout, which has the effect of setting its parent for you. This memory will be freed when the parent object is (same true for the QLCDNumber objects).
The model object marked "OFFENDING CODE" is unparented and may stay that way depending on what View::setModel() is doing.
wrote on 28 Jul 2022, 09:10 last edited byWhere I added the comments with the offending code.
I had to set the parents of some of the objects because it actually did not cleanup when the objects were destroyed, contrary to expectations.
One of the error was on me because my game class wasn't properly destructed (and isn't a Qt object).
1/3