So, I've learned so far, that Qt releases the memory of all child objects when a parent object gets deleted. Also, one generally doesn't have to care about memory management for objects created on the stack (i.e. NOT as pointers).
Now, when I did the very good "AddressBook" tutorial, I found this in part 5:
AddressBook::AddressBook(QWidget *parent) : QWidget(parent)
{
dialog = new FindDialog;
}
Complete source is available:
addressbook.h
addressbook.cpp
finddialog.h
Here, dialog is a private member of AddressBook, and it is a pointer to a FindDialog. FindDialog inherits QDialog, but no this-Pointer is passed to the constructor (as seen above). No explicit destructor exists, there is no delete dialog-call...
Also, not passing this seems to be intentional:
[The FindDialog's] constructor is defined to accept a parent QWidget, even though the dialog will be opened as a separate window.
Wouldn't this cause a memory leak? Or is there some other mechanism that will silently delete dialog and free its memory?
Thanks in advance for any help!
Update: I posted this issue to the qt-project.org forums and it should get fixed soon.
There is no excuse for this, and it eventually has more issues than you just bring up, namely:
It is not managed as you say.
It does not use the conventional new Foo() syntax.
It is not done in the constructor's initializer list.
The OS will probably free this up once the application quits, but still, I always speak up against such issues, anyhow, especially in example projects. The appropriate fix would be to use either a stack object instead of the heap object or QPointer in my opinion.
See the following post for details in case the latter:
How to crash (almost) every Qt/KDE Application and how to fix
This should be reported and fixed upstream; good catch!
I have just submitted a change to Gerrit about this in here.
Related
there. I've seen this example from qt: https://doc.qt.io/qt-5/qtwidgets-widgets-calculator-example.html, and wonder why qt always create widgets with new instead of allocating on stack
Button *Calculator::createButton(const QString &text, const char *member)
{
Button *button = new Button(text);
connect(button, SIGNAL(clicked()), this, member);
return button;
}
create widget on stack is faster, and in this question: QT-specific difference of stack vs. heap attributes?
Mike's answer says that create on stack is perfectly fine, but why official documents use new mostly?
This is simple: because you want the widget to live even after this function scope is finished and QObjects are not copyable. The following code does not work because you cannot copy the object.
Button Calculator::createButton(const QString &text)
{
Button button(text); // allocated on stack, it is OK so far...
return button; // nope, you cannot copy that! it does not compile.
}
The following code does not work either because you would be passing a deleted object.
Button *Calculator::createButton(const QString &text)
{
Button button(text); // allocated on stack, it is OK so far...
return &button; // ... returning pointer, still OK...
// Oh no! End of scope here, the object gets murdered now.
// whoever holds the pointer to it, holds a dead, invalid object.
}
The object gets deleted at the end of scope and you would be passing a pointer to freed, hence invalid memory.
The example you referred to
class Widget2 : public QWidget
{
Q_OBJECT
public:
Widget2(QWidget* parent = nullptr);
private:
QPushButton button;
};
does not necessarily mean that the button is created on the stack. It depends on how the instance of Widget2 is created. If it is on the stack, then also button is on the stack. If it is newed on the heap, then also button is on the heap. The difference from the "normal" case where button is declared and kept as a pointer is that in the example above they are allocated together in one allocation. Yes, it is negligibly faster but it is just a premature optimization. Allocation of widgets will never ever be your bottleneck, believe me. Btw. most objects in Qt are implemented using PIMPL idiom to preserve binary compatibility, so they internally allocate their private objects on the heap anyway.
Yes, you can keep your button as a NON-pointer member. This is legal. But it is not wise. There is an issue with this approach: you must #include all the subwidgets in the header and you cannot forward-declare them. Which definitely makes you compile time longer. But that is not the main problem, you can wait a little. The bigger problem is that you are introducing building dependencies which makes your code less composable. Imagine you have your custom widgets split into multiple libraries - then everything what you #include in your headers visible to other modules also requires to be visible to these modules. This soon becomes unmanageable mess because you will not be able to hide/encapsulate implementation details. And the fact that your widget uses some button certainly is an implementation detail. Just keep as little details in your header as possible. Keeping a pointer (can be forward-declared) is definitely less of a burden than keeping a non-pointer member (must be #included!). Moreover if you keep a pointer, then you can use substitution principle and this pointer can actually point to any subclass instance. In little toy applications or school homeworks this does not matter but when you are designing a really large application wit lots of modules and submodules organized as libraries or when you are writing libraries which are to be used by others, then these things REALLY DO matter. This makes the difference between well maintainable and totally unmaintainable code.
In my practice I have encountered only two usecases where widgets are actually allocated on the stack. First is when they are created in main() where you can write:
int main() {
QApplication app;
MainWindow w; // it is really on the stack
w.show();
return app.exec();
// here is the main window automatically destroyed
}
Another case is when you open a display a modal dialog with a blocking event loop using exec().
void showSomeMessage() {
QMessageBox box; // yes, we should set a parent here, for sake of simplicity I omitted it
// etc. set text and button here
box.exec(); // blocking here, we are waiting for user interaction
// end of scope - we are done here, we do not need the message box any more
// so it is perfectly fine it gets automatically deleted here
}
These cases are perfectly fine. Actually, as you can see blocking exec() in both these cases, they are very similar.
Conclusion: it is better to declare member QObjects or QWidgets via pointers and always forward-declare them in your headers instead of #includeing their headers. This way you can design more composable, maintainable and future-proof code. You will not see any significant difference in small toy projects, but you will benefit from this good practice when your codebase grows larger. Even better habit is to keep them via QPointer (which a special Qt weak pointer), which has twofold benefit: 1) it is automatically initialized to nullptr and 2) when the objects gets destroyed, the pointer is automatically set to nullptr so you can easily check if it is alive. Plus QPointer provides implicit conversions to raw pointer so it does not affect the way you write your code. It is a very handy class.
So, I think I've searched the web quite thoroughly about this and found nothing really useful (just confusing at most...).
I'd like to know how I can (if possible) use Qt with non-dynamic memory. The problem I face is that for many widgets, I know exactly what I want to use (these sub-widgets, these layouts, in fixed numbers, etc.). Yet, everything in Qt seems to get in the way when you don't use dynamic memory. A simple example is QLayout, which from the Qt documentation is designed to take ownership of anything it is added. So basically, the following code:
//In header
class ThumbnailDialog : public QDialog
{
Q_OBJECT
public:
ThumbnailDialog(QWidget* parent = 0);
~ThumbnailDialog(void);
private:
QPushButton m_confirm;
QPushButton m_cancel;
QHBoxLayout m_buttonsLayout;
};
//Implementation of ctor
ThumbnailDialog::ThumbnailDialog(QWidget* parent):
QDialog(parent)
{
//...
m_buttonsLayout.addWidget(&m_confirm);
m_buttonsLayout.addWidget(&m_cancel);
//...
setLayout(&m_dialogLayout);
}
...will end up (on MSVC) in a debug assertion fail for _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) because, in the ThumbnailDialog's dtor, the layout tries to delete the buttons... which it obviously shouldn't.
So, am I forced to use dynamic memories everywhere, as this "Qt Expert" advocates (while mentioning "heap", though...) ? This seems wrong as this prevents taking advantage of RAII (if parent-child relation means there'll be a delete, one can't use smart pointers to do that I suppose, then). It also feels terribly wrong to resort to dynamic memory for things known at compile-time... (but I could be wrong, that's just my feeling).
So: is there any way of using Qt without resorting to dynamic memory and news for every single widget/layout ?
I think you are misunderstanding the problem here. You are not double deleting something, you are deleting an object allocated on the stack:
int foo = 12345;
int* pFoo = &foo;
delete pFoo;
This is what happens when you pass a pointer to a stack based object to QHBoxLayout, hence your heap corruption debug assert.
Qt manages QObjects this way because most GUI's have LOTS of widgets, which makes managing GUI object life times easier, it also allows queued deletes across threads etc. Also internally most classes use PIMPL's so you are not avoiding the heap/dynamic allocation even if your code worked.
Having said all this you can get it to work without the heap alloc if you wish, but it is far more effort than its worth. In your example you would have to remove the widgets from the layout in the destructor, but be sure the nullptr check things in case the ctor has thrown, if they're not in the layout when its destructor is hit then it won't be able to delete them.
One more thing to think about.. if Qt was designed to work this way then you could easily end up in the situation where you overflow the stack on some platforms. E.g Qt works on Symbian/S60 which has extremely limited stack, running your code there could easily cause a stackoverflow :).
Yes, there is. (and in a pretty clean way, I believe)
You just have to be aware about the order of destruction of your QObject hierarchy:
As explained in the Qt docs, a lot of objects claim ownership of their children and therefore want to make sure they get cleaned up when they die.
QObject’s dtor relieves its parent of that ownership.
Destruction of non-static data members happens from bottom to top.
Which means that, in your case, you just have to move the layout to the top:
private:
QHBoxLayout m_buttonsLayout;
QPushButton m_confirm;
QPushButton m_cancel;
All the layout’s children’s dtors unregister themselves from the layout, so when the layout destruction happens there are no registered childs left.
Previously the layout’s destruction deleted the children which where not newd in the first place.
This may seem tedious at first sight, but in practice the hierarchy within a custom widget is pretty flat. The order of widgets in one layer of the hierarchy – in this case the QPushButtons – is not important which usually means that you only have to arrange the layouts on top properly.
The problem you're seeing is that you're not thinking about what is happening. The QPushButton instances in the class are created and owned by the class. When the class is deleted, it will call the destructor on the QPushButtons.
Qt provides useful parenting of objects and deleting a parent will handle deletion of all its child objects.
So, in the case of your example, you have two things that are going to call the destructor on the QPushButtons: 1) The deletion of the class object for ThumbnailDialog and 2) The deletion of the buttonlayout, which will try to delete its children and will fail, as the object is on the stack.
What you can do, if you really want, is ensure that the QPushButton items are removed from the button layout, in the destructor of ThumbnailDialog by calling removeWidget() on the button layout.
However, this is messy. Dynamic allocation is a much better method, as it allocates objects on the heap and not the stack.
Also note, with Qt's parenting, it means that you can create a lot of widgets without needing to keep track of them. For example, you can do this: -
ThumbnailDialog::ThumbnailDialog(QWidget* parent):
QDialog(parent)
{
//...
m_buttonsLayout.addWidget(new QPushButton("Confirm"));
m_buttonsLayout.addWidget(new QPushButton("Cancel"));
//...
setLayout(&m_dialogLayout);
}
In this case, the push buttons don't even need to be defined in the header and you can be assured that they'll be deleted along with their parent.
No, not really. I'm afraid. Qt relies on this stuff.
If you have read the other answers and you still want to use static allocation, you can release the ownership that was taken when doing addWidget():
//...
m_buttonsLayout.addWidget(&m_confirm);
m_buttonsLayout.addWidget(&m_cancel);
// release the ownership by setting no parent
m_confirm.setParent(0);
m_cancel.setParent(0);
//...
This resource describes a method of creating a modeless dialog using pointers. They create a pointer that pointer to the dialog class and then use the -> syntax.
CModeLess *m_pmodeless = new CModeLess(this);
m_pmodeless->Create(CModeLess::IDD);
m_pmodeless->ShowWindow(SW_SHOW);
I have been doing something like this so far:
CModeLess m_pmodeless;
m_pmodeless.Create(IDD_DIALOG);
m_pmodeless.ShowWindow(SW_SHOW);
I do this mainly because I feel comfortable using classes. Is there any disadvantage of using this approach?
Secondly, in the pointer approach I have to do something like this to close the window: (if I am not mistaken)
if(m_pmodeless != NULL) { delete m_pmodeless; }
Is there some deletion I have to do If I use classes or is m_pmodeless.closeWindow() enough?
I apologize if this is a very basic question, but i'm curious to know.
This is a tricky question to answer, as a lot depends on exactly what you are trying to do and also on exactly how CModeless is implemented. In general you are right to avoid pointers, but GUI programming has special issues because the C++ objects in your program represent GUI objects on the screen, and coordinating the destruction of the C++ objects in your program with the GUI objects on the screen can be quite tricky. Sometimes pointers are the simplest answer to this problem.
I'm assuming that m_pmodeless is a member variable of another class.
One issue is the lifetime of the objects. In the class version the CModeless object will be destroyed when the containing object is destroyed. Whether that's OK for you depends on your code. Whether that also destroys the modeless dialog depends on how CModeless is implemented. You need to look at the CModeless destructor if you can, or the documentation for CModeless if you can't. With the pointer version you have explicit control over when the object is destroyed, just call delete at the right time.
Another issue is that some GUI libraries automatically delete the C++ object when the GUI object is destroyed. Something like this (on Windows)
case WM_NCDESTROY:
...
// last message received so delete the object
delete this;
break;
Code like this is assuming that all your objects are heap allocated and automatically deleting them for you at the right time. If CModeless is written like this then you have no choice but to use the pointer version.
My coding practice using Qt can best be described as follows:
If the Widget is going to be actively used (e.g. A QLineEdit which provides text), I declare it in the header file and then initialise it in MainWindow.cpp.
e.g. TextEditor.h:
class TextEditor
{
//other code
private:
QLineEdit edtFind;
};
2.. If a widget is not going to be used (e.g. QLabel, QWidget), or it's part of a signal slot system (e.g. QPushButton), I declare and inialise it inside constructor using new.
-e.g.
TextEditor::TextEditor()
{
//other code
QWidget* searchPanel = new QWidget();
edtFind = new QLineEdit("Enter Search Term");
QPushButton* findButton = new QPushButton("Find");
connect(findButton,SIGNAL(pressed()),this,SLOT(find()));
ui->statusbar->addPermanentWidget(searchPanel);
}
My question is, am I using an efficient approach in point 2? Would it be better to not allocate memory from the heap?
Thanks.
Your approach is not efficient. You should use heap allocated objects when you actually need them:
objects that have a longer lifetime
using a forward declaration in order to avoid including a header file
holding a reference to an object created elsewhere
Your approach is more complicated without any visible benefit. Heap is known to be slow, and allocating a large number of small objects is known to fragment it (this might not make a difference in your app but it's still a bad practice).
While good advise for C++ in general, answer 1 is actually wrong for a big part in Qt: QObject (and with it all widgets, since QWidget derives from QObject). Rule there is to always allocate QObjects on the heap if they have a parent, because QObject features a parent-based garbage collection (when the topmost QObject-parent gets deleted, it will ask all its children to delete themselves recursively). The application may try to delete an object on the stack, which leads to a crash.
Note that some operations in Qt implicitly add or change the parent of a QObject as a side-effect (reparenting), such as adding a widget to a layout. However, this is usually documented in the API documentation. Since reparenting is very common with QWidgets, you should never put them on the stack. Other QObject-derived classes are safer, consult the API documentation in case of doubt.
Sorry for the dumb question, but I'm working with Qt and C++ for the first time, and working through the tutorial and some samples.
One thing that was mentioned was that Qt stuff doesn't need to be explicitly deleted. So, main question, does this also apply to collections of Qt stuff? Like say I want a dynamic number of MyWidgets, so I keep a vector or whatever of them. Are they still taken care of for me?
As a side question, what is going on to make it so I don't have to worry about destructors?
The Qt memory management model is based upon a parent-child relationship. Qt classes take an optional parent as a parameter of their constructor. The new instance registers with this parent such that it is deleted when the parent is deleted. If you are using a Qt collection (e.g. QList), I believe you can set the list as the parent of its entries. If you're using an std::vector or other collection type, you will not get "automatic" memory management.
The Qt model makes a lot of sense in a UI hierarchy where it matches one-to-one with the UI hierarchy. In other cases, it doesn't always map as cleanly and you need to evaluate whether using the Qt system makes sense for the particular situation. The normal C++ tools still work: you can use std::tr1::shared_ptr or any of the other smart pointer classes to help you manage object lifetime. Qt also includes QPointer, a guarded pointer, and the QSharedPointer/QWeakPointer pair that implement a reference-couting smart pointer and weak-reference pair.
Qt has an interesting object model for sure. When I first started it made me uneasy that there were so many new Foo calls and no deletes.
http://qt.nokia.com/doc/4.6/object.html Is a good place to start reading up on the object model.
Things of interest:
QObject subclasses have their assignment and copy-ctor methods disabled. The chain of object child-parents is maintained internally by QObject.
Generally when instantiating a QObject subclass (if you don't plan on managing its pointer yourself) you will provide another QObject pointer as the parent. This 'parent' then takes over the management of the child you just made. You can call setParent() on a QObject to change who "owns" it. There are very few methods in Qt that will change the parent of an object, and they all explicitly state that they do in the docs.
So to answer your specific question: it depends on how you made all of your MyWidget instances.
If you made each one with a parent, then no you don't have to delete them. The parent will delete them when it gets deleted.
If you're keeping a QList<MyWidget*> collection of them, and you didn't give them a parent, then you should delete them yourself.