Does QObject distinguish between stack and heap allocated children when deleting? - c++

According to the Qt documentation:
QObjects organize themselves in object trees. When you create a
QObject with another object as parent, the object will automatically
add itself to the parent's children() list. The parent takes ownership
of the object; i.e., it will automatically delete its children in its
destructor.
For me that implies when a QObject is being deleted, it goes through and calls delete on all the pointers it stores in its children list.
However, it is not necessary for children to be dynamically allocated, and it is perfectly legal to build QObject trees with stack allocated objects.
According to standard specifications, calling delete on a pointer that does not point to a dynamically allocated object is undefined behavior, which may result in anything from "nothing" to a program crash.
IMO it is unlikely for QObject, which is pretty much the backbone of the almost the entire collection of Qt classes to rely on something that could produce undefined behavior.
So, does QObject distinguish between stack and heap allocated children when deleting? And if so, how exactly?

However, it is not necessary for children to be dynamically allocated,
and it is perfectly legal to build QObject trees with stack allocated
objects.
No. See QObject::~QObject():
Warning: All child objects are deleted. If any of these objects are on
the stack or global, sooner or later your program will crash.

Related

Can I use QCoreApplication::instance() for Orphan QObjects?

For QObjects created on the heap with no parent, I found that destructor is not called. So, I starting using the core application instance as their parent to ensure that they are cleaned by garbage collector. Is this the right action, or what should I exactly to safely de-allocated these objects?
Here is an example of what I am doing:
// Use application instance as parent to avoid memory leak if object is not deleted
m_qObject = new DataHandler(QCoreApplication::instance());
Qt doesn't have an independent memory management, such as a garbage collector. The explicit parent-child relationship used is a classic ownership model that helps in the automatization of object life-cycles, it is deterministic (it will delete object on parent's destruction), and it is very natural with user interfaces.
If an object is created (in the heap) without a parent, it will generate a memory leak when the last reference to it is lost. Objects in the stack should not have a parent to prevent double-delete errors (check Qt documentation for further information)
If you set QApplication::instance as the parent of an object, you are basically telling it not to be destroyed until the application quits. If that's the case, then there is no such a great difference with other standard memory leaks, escept the object's destructor does something else than just releasing memory (such as closing OS-wide handles, saving files, etc).
There is a very interesting case I was curious about: what happened when the original parent (Q*Application::instance) was replaced at any given moment, as in this question?
The case is that the ownership of the object is transferred from the former Q*Application instance to the new one. It may become a problem if you rely on the existence of the object through the whole application life-span but several instances of Q*Application are allowed to be created and destroyed at any moment. One scenario would be a non-Qt application loading plug-ins or components built on Qt, in where you cannot control the creation/destruction order.
If that's the case, I'd suggest to find another way to destruct your object, such as having your own singleton inheriting from QObject that you can use as parent.

qt garbage collection and smart pointers

Im thinking of starting using smart pointers in my qt work.The thing that confuses me how smart pointers would go with Qt garbage collection. The whole Qt stands on idiom that child QObject constructs with QObject* parent as ctor argument and therefore enables garbage collection.
For example:
QWidget* mWidget = new QWidget(this);//Here we not only
//ensure that mWidget will be deleted
//when its parent is deleted, but also tell qt,
//that mWidget is not a window, but belongs to
//parent's layout
Now if i want to wrap mWidget into the smart pointer.
typedef QScopedPointer<QWidget> WidgPtr;
WidgPtr mWidget = WidgPtr(new QWidget(this));
But now when parent's dtor is called it will call delete on mWidget's pointer twice. First due to garbage collection, second when smart pointer dtor is called.
Of course we can construct mWidget without parent and then change some flags to turn off window behaviour or call setParent() (But then again mWidget will be deleted twice). But to me its too much to do such a complex initialization only to be able to use smart pointers instead of raw pointers.
Or maybe i miss something?
Thanks.
QScopedPointer and QSharedPointer are not aware of whether their target object lives or dies, so if you keep the smart pointer anywhere else than among member variables, then yes, in your case destructor might be called twice. That's why these kinds of smart pointers are badly suited for QObjects (but they can still be useful when your object doesn't have a parent).
If you need to keep a guarded pointer to QObject, use QPointer: it will become null once the object is destroyed, so you can delete it at any moment without fear of causing any mayhem. But remember that QPointer will NOT destroy referenced object in destructor. In most cases you should build hierarchies of QObjects and just let the ownership system clean up the memory.

Dynamic memory Deallocation in QT

How does the dynamically allocated pointers in QT coding are destroyed because we don't write a specific destructor for them?
To expand on Neox's answer, Qt has two methods for object management:
QObject tree structure
Managed pointer classes
And the two don't really mix very well for reasons which will become apparent.
QObjects can either be 'free' or have a parent. When a QObject has its parent set (either by providing the QObject constructor with a pointer to another QObject, or by calling setParent()) the parent QObject becomes the owner of the child QObject and will make sure any of its children are destroyed when it is. There are also several methods available to inspect child/parent relationships.
A separate method of managing dynamically allocated objects are the managed pointer classes which this paper explains quite well. To summarise though:
"The QScopedPointer class stores a pointer to a dynamically allocated object, and deletes it upon destruction" and is therefore good when you need objects which have clear and obvious ownership and lifetime.
"The QSharedPointer class holds a strong reference to a shared pointer [and] will delete the pointer it is holding when it goes out of scope, provided no other QSharedPointer objects are referencing it" and is therefore good when ownership is not as clear cut, but you want to make sure it doesn't get lost and become a memory leak. QWeakPointer can be used to share the pointer without implying any ownership.
As you can see, some of the guarded pointer classes can be used with a QObject tree, but you should make sure you read and understand the documentation thoroughly before doing so or you may end up with a corrupt data structure.
The short answer is:
QObjects organize themselves in object trees. When you create a QObject with another object as parent, it's added to the parent's children() list, and is deleted when the parent is.
Qt has a good docu about object hierarchy and ownership within the framework. You can read it here

Parent/Child class ownership semantics

I've been building a system with a parent object, where it creates various child objects, and each child object requires a master object to function. Now, so far, I've been creating shared_ptr<Parent> and Child*, so when the creator of Parent and all the Childs are gone, the Parent goes too.
But I'm re-designing my API so that Child can be created on the stack (previously it was just the heap). Now I'm unsure about what to do with Parents, as I don't see why they shouldn't also be creatable on the stack- in terms of their actual function- but what happens if Parent is destroyed and then someone tries to use a Child that they moved, copied, or allocated on the heap? Should I just throw an exception? Skip performing the operation? Or just stick to allocating Parents on the heap?
Here's the problem sentence
if Parent is destroyed and then someone tries to use a Child ...
If this is possible then you have shared ownership, which implies creation on the heap.
So, either you stick to heap allocation or drop the shared ownership semantics. There is no other way. weak_ptr is merely away of advertising the state of a shared object.
If you really want to do what you're advertising:
if Parent is destroyed and then someone tries to use a Child ...
This is going to cause a problem as #spraff mentioned.
The way to achieve what you are saying is to also make the Child a shared_ptr and allow a shared ownership between the Parent and also whatever else is trying to use the child...

Creating and deallocating a Qt widget object

I heard that the widgets should be allocated on the heap (using new), and then there are no needs to delete them (it is done automatically).
Can someone explain why?
What happens if a widget is not allocated that way, but on a stack?
I am not sure if it matters, but all widgets I am creating have a parent.
This says :
If parent is 0, the new widget becomes
a window. If parent is another widget,
this widget becomes a child window
inside parent. The new widget is
deleted when its parent is deleted.
There's no magic involved. Simply put, a QObject automatically deletes its children in its destructor. So, as long as your widget has a parent and that you destroy that parent, you don't have to worry about the children. So if you wondered what was that QObject * parent parameter, well, that's what it's there for.
Also, from the doc:
All child objects are deleted. If any of these objects are on the stack or global, sooner or later your program will crash.
So, avoid giving parents to objects that are stack-allocated.
The docs on this are here. The reason they are most often allocated on the heap is to avoid problems caused by construction order of the members of the object tree. The stack is fine so long as you follow the rules, but why bother when you have a reliable alternative?
The reference #Etienne cited is here.