PDA

View Full Version : Memory management in Qt programs



franky
8th April 2019, 09:55
Hi all,

I've got a Qt project which the statement below is written in its .cpp file's constructor:


setAttribute(Qt::WA_DeleteOnClose);

The program, by the way, inherits from QMainWindow:

in the header file:

class MyProgram : public QMainWindow

I think the meaning of the first statement is that, when I close the project (MyProgram), the Qt Creator compiler (MinGW) deletes all objects created by new in the project.
Is it right up to here?

If so, why is it needed whatsoever? When we close the project, on Windows/Mac etc, all objects, statements, functions and whatever exists inside the project will be freed/deleted and when we open the project once again, they will be assigned once again. So, I don't know why we still need:

setAttribute(Qt::WA_DeleteOnClose);

To me, it does nothing and is redundant.

Am I wrong, please?
If possible please guide me in this case.

Ginsengelf
8th April 2019, 14:34
Hi, WA_DeleteOnClose means that the widget where it is set will be deleted when the widget is closed (see https://doc.qt.io/qt-5/qt.html#WidgetAttribute-enum). This will not delete all objects created by new (only those whose parent is the widget with WA_DeleteOnClose set).

Ginsengelf

anda_skoa
8th April 2019, 18:59
If so, why is it needed whatsoever?

It is not needed, it is convenient.

For example with a sub window that is created on demand, deleted when it is no longer needed and re-created on demand again.
E.g. a Find/Replace dialog, a log/debug view window, etc.



When we close the project, on Windows/Mac etc

Ending a program is something entirely different.

Explicitly deleting/freeing resources during runtime is about controlling the resource usage of the program while it is operational.

Obviously no resources are needed anymore when the process stops existing.
But even then it is still a good idea to explicitly release resources as this allows control over order of release and to run code during release.

Cheers,
_

franky
9th April 2019, 12:29
So it's for a sub window. When we close it, its resources will be free.

> But even then it is still a good idea to explicitly release resources as this allows control over order of release and to run code during release.

I can't understand it completely, may you explain it more or using an example?

anda_skoa
9th April 2019, 13:18
So it's for a sub window. When we close it, its resources will be free.

It works on any kind of widget. A sub window is one of the use case.



> But even then it is still a good idea to explicitly release resources as this allows control over order of release and to run code during release.

I can't understand it completely, may you explain it more or using an example?

For example if your program has an open network connection, then explicitly closing it will notify the other side.
If the program just terminates then the other side will run into an error or timeout, potentially much much later then if it had been notified about the connection being closed.

Cheers,
_

franky
9th April 2019, 13:52
Thank you.

By "explicitly closing it" do you mean using the "delete" keyword or the functions which are built to perform this task like "setAttribute(Qt::WA_DeleteOnClose);"?

And should we do this (explicitly closing) for any kinds of resources whether they're widgets, containers or something else that are created using "new"? I mean, when we dedicate something using the keyword "new" to something else we must somewhere in the code free that thing either using "delete" or a function like the above one. Right?

anda_skoa
9th April 2019, 16:29
By "explicitly closing it" do you mean using the "delete" keyword or the functions which are built to perform this task like "setAttribute(Qt::WA_DeleteOnClose);"?

Yes. In the case of the socket, potentially even calling close() or disconnectFromHost(), but I think the destructor does that as well.



And should we do this (explicitly closing) for any kinds of resources whether they're widgets, containers or something else that are created using "new"? I mean, when we dedicate something using the keyword "new" to something else we must somewhere in the code free that thing either using "delete" or a function like the above one. Right?

Right.

Or using smart pointers for resources allocated with "new" and which are not widgets with DeleteOnClose or in general QObjects with a parent.

The rule of thumb is: if it has been created with "new" it must be destroyed with "delete", unless ownership of the pointer is transferred to a different mechansim.
Such mechanisms can be smart pointers, QObject parent/child relationship, or things like DeleteOnClose for widgets.

Cheers,
_

franky
9th April 2019, 20:54
Thanks so much, I got many things.

One thing:
> QObject parent/child relationship

Does it mean that we mustn't delete such a thing? Or do you mean that in such a relationship we only need to delete the parent and the children are freed afterwards?

So in this mechanism too, we need deletion, not?

anda_skoa
10th April 2019, 08:14
> QObject parent/child relationship

Does it mean that we mustn't delete such a thing? Or do you mean that in such a relationship we only need to delete the parent and the children are freed afterwards?

Yes, correct. In a QObject tree, a node will delete its children when it itself is being deleted.



So in this mechanism too, we need deletion, not?

Well, the root node of a QObject tree will need to be deleted if it has been created with "new".
This deletion can be explicit or use any of the other techniques mentioned earlier

Cheers,
_

franky
10th April 2019, 09:19
Thanks so much.

One thing about resources built using methods apart from "new". For instance, a class embracing a number of data members and member functions in a C++/Qt/QML project. At times in such projects I still see a destructor while there's not any keyword "new" in the code. So for such projects/codes since there is no memory allocated/assigned using "new", we mustn't make the code more complicated by declaring and defining destructors or other mechanisms to delete the objects or generally the resources in the code. Do you agree?

anda_skoa
10th April 2019, 13:57
The destructor is the code that is run when an object is destroyed.

It can be used to call delete on pointer members of that class but of course it can do other things as well, e.g. calling close() on a socket.

It will run independent of how the object itself is being destroyed, e.g. deleted after new or simply falling out of scope when allocated on the stack.

Sometimes classes have an empty constructor to enable forward declaration of certain members, e.g. the template values of smart pointers.

Essentially the same rules as for constructors: if the class doesn't need any special initialization, then the constructor generated by the compiler will be good enough.
If the class doesn't need any special deinitialization, then the destructor generated by the compiler will be enough.

Rule of thumb: if you have pointer based members you likely want both.

Cheers,
_