Does qApp delete all the program windows?
-
wrote on 10 May 2014, 12:29 last edited by
I have a program that, from its QMainWindow MainWindow object, creates a few instances w1..wn of QWindow objects. They are NOT child objects of my MainWindow.
When QMainWindow is closed by user clicking on the "x" button on the upper bar system menu, w1..wn remain visible.I understand that this is because the program survives even without its main window.
But I don't want this, and therefore I've added:@void MainWindow::closeEvent(QCloseEvent *event)
{
qApp->quit();
}
@Now when the user closes the main window all windows disappear.
My question is: does this also delete the windows' memory correctly?
I could not find an answer to this in the Qt documentation nor in any blog.My idea is that if qApp is able to keep track of the fact that I've created windows w1..wn and can close them, it can also free the related memory.
Is it true?
-
wrote on 10 May 2014, 13:03 last edited by
If attribute DeleteOnClose is setted up on each of them, then they should be properly freed afaik.
-
wrote on 10 May 2014, 13:18 last edited by
Does qApp->quit() close the remaining windows at all? I don't think so, as calling qApp->quit() will just make QApplication::exec() return. Usually it is done the other way around: qApp will quit as soon as the last window is closed. See "QApplication::lastWindowClosed()":http://qt-project.org/doc/qt-4.8/qapplication.html#lastWindowClosed for details.
__
You can try with this code:
@int main(int argc, char* argv[])
{
QApplication *app = new QApplication(argc, argv);
QDialog *dialog = new QDialog();
QPushButton *button = new QPushButton(dialog);button->setText("QApplication::quit()");
QObject::connect(button, SIGNAL(pressed()), app, SLOT(quit()));dialog->show();
app->exec();printf("QApplication::exec() has quit...\n");
getchar();return 0;
}@If you click the button, the window will not be closed. Instead it will just "freeze", because event processing has been stopped.
-
wrote on 10 May 2014, 19:19 last edited by
I have my own program showing that qApp->quit() closes all windows.
It is below here.
If you run it as is, closing the main window closes also w2.
But if we delete the row qApp->close() this does not happen anymore.@int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();return a.exec();
}
@@MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
btn = new QPushButton("new Win", this);
w2=new QWindow();
QRect r=w2->geometry();
r.moveTop(200);
w2->setGeometry(r);
move(0,0);
connect(btn,SIGNAL(clicked()),this,SLOT(btnClicked()));
}void MainWindow::btnClicked(){
w2->show();
}void MainWindow::closeEvent(QCloseEvent *event)
{
qApp->quit();
}
@ -
wrote on 10 May 2014, 19:36 last edited by
And...
does anyone know any difference (if w is the pointer to a window without parent) between the following two rows?
AFAIK they are totally equivalent, but I would like to share this conclusion with someone.@delete w;
@@w->close();@
-
wrote on 10 May 2014, 19:50 last edited by
No, they certainly are not equivalent! The first code will delete the window object and release all memory that belongs to it. The second code will only close the window, but the window object remains in memory! You can close a window and later show it again. Destroying the window object of course implies closing the window, but the other way around this is not true!
_
As mentioned before, the Qt::WA_DeleteOnClose attribute can be set. If, and only if, that attribute is set, Qt will implicitly delete the window object when it's closed. But that still doesn't make the delete operator and the close method "equivalent". It only means that delete will be invoked inside close().
-
wrote on 10 May 2014, 19:52 last edited by
[quote author="mcwork" date="1399749548"]I have my own program showing that qApp->quit() closes all windows. [/quote]
The only reason why in your program QApplication::quit() will "close" all windows is because your program will terminate right after QApplication::exec() returns. Of course all windows will disappear if the program terminates. Still those windows are never closed properly! Following your argument, we could claim that calling exit(42) closes all windows ;-)
Try putting a getchar() after the a.exec() and you'll see they are not closed:
@const int ret = a.exec();
getchar();
return ret;@ -
wrote on 11 May 2014, 06:42 last edited by
[quote author="MuldeR" date="1399751404"]No, they certainly are not equivalent! The first code will delete the window object and release all memory that belongs to it. The second code will only close the window, but the window object remains in memory! [/quote]
This is what I believed up to yesterday morning when I read the following from Qt 5.2 help about bool QWindow::close():
This closes the window, effectively calling destroy(), and potentially quitting the application. Returns true on success, false if it has a parent window (in which case the top level window should be closed instead).
However your answer is what I hoped: experienced programmers prefer to rely on the standard "delete" rather than a help comment that might be written with unclear words.
-
wrote on 11 May 2014, 07:11 last edited by
[quote author="MuldeR" date="1399727923"]
__You can try with this code:
[/quote]@int main(int argc, char* argv[])
{
QApplication *app = new QApplication(argc, argv);
QDialog *dialog = new QDialog();
QPushButton *button = new QPushButton(dialog);
[...]
@Ehm.. May I ask you a final question?
I've seen that you don't bother about deleting app, dialog, button objects.
In past years, AFAIK, this would have caused memory leakage to the OS.
I've read that "modern operating systems" are able to automatically delete all the memory allocated by an application when it terminates.
Is it true? can you tell me a link where to read more about this?Thanks again.
-
wrote on 11 May 2014, 11:40 last edited by
[quote author="mcwork" date="1399790537"]This closes the window, effectively calling destroy(), and potentially quitting the application. Returns true on success, false if it has a parent window (in which case the top level window should be closed instead).[/quote]
Not quite sure where you read that, but I think the manual is quite explicit about what happens when you call close(), see "here":http://qt-project.org/doc/qt-5/qwidget.html#close:
[quote]bool QWidget::close() [slot]Closes this widget. Returns true if the widget was closed; otherwise returns false.
First it sends the widget a QCloseEvent. The widget is hidden if it accepts the close event. If it ignores the event, nothing happens. The default implementation of QWidget::closeEvent() accepts the close event.
If the widget has the Qt::WA_DeleteOnClose flag, the widget is also deleted. A close events is delivered to the widget no matter if the widget is visible or not.
The QApplication::lastWindowClosed() signal is emitted when the last visible primary window (i.e. window with no parent) with the Qt::WA_QuitOnClose attribute set is closed. By default this attribute is set for all widgets except transient windows such as splash screens, tool windows, and popup menus.[/quote]
So by calling close() it's not even sure that the widget will be closed at all, because the CloseEvent can be rejected. And also deleting the widget is completely optional - it does not happen by default!
__[quote]Ehm.. May I ask you a final question?
I’ve seen that you don’t bother about deleting app, dialog, button objects.
In past years, AFAIK, this would have caused memory leakage to the OS.
I’ve read that “modern operating systems” are able to automatically delete all the memory allocated by an application when it terminates.
Is it true? can you tell me a link where to read more about this?[/quote]If I did not delete an object allocated on the heap, then that was because the sample code was intended to illustrate something else. I do not include all details of the program in a short code excerpt. In a "real" program I (hopefully) will properly delete all objects allocated on the heap, of course ;-)
Anyway. Yes, on modern OS, when your process terminates, all of its memory is released - no matter what. So one could argue that we must not delete QApplication when the process is going to terminate anyway. But there are two things to consider: First of all, if you never properly delete an Object, then its destructor is never called. Imagine that QApplication (or whatever object) needs to save some important data on the Hard Disc in its destructor. If you never properly delete it, the destructor is never is called and all unsaved data lost! Furthermore, sometimes you may wish to scan your program for memory leaks, with a tool like Valgrind or VLD or Dr. Memory. This of course requires that your program always exits "cleanly".
To make a long story short: If you allocate an object on the heap, then also make sure you are going to delete it when it's no longer needed!
-
wrote on 11 May 2014, 16:07 last edited by
bq. Not quite sure where you read that, but I think the manual is quite explicit about what happens when you call close(), see "here":http://qt-project.org/doc/qt-5/qwidget.html#close:
[/quote]The link you suggest is for QWidget, mine relates to QWindow. It is "here":http://qt-project.org/doc/qt-5/qwindow.html#close:
Both inherit QObjects, but are in different branches of the inheritance tree.So, it appears that for QWindow::close() does something very similar to "delete". There must be some difference, otherwise there were no reason for creating a specific function, but the help is not clear.
So, because it is unclear what is this difference, better is to rely on C++'s keyword delete for actually deleting (and freeing the memory).bq. Anyway. Yes, on modern OS, when your process terminates, all of its memory is released - no matter what..
This is very important, even though there are the 'two things to consider' you mentioned. Indeed this mechanism is a backup for the cases in which we forget to delete something, and ensures that our program cannot be harmful to others', even in case of bugs, after its closing.
bq. To make a long story short: If you allocate an object on the heap, then also make sure you are going to delete it when it's no longer needed![/quote]
I will adopt this suggestion, but I also will know that for fast pieces of code one could just allocate what he needs and let the OS make the free actions that are mandatory to leave the system clean from our stuff (like your example posted yesterday)
-
wrote on 11 May 2014, 16:46 last edited by
.
-
wrote on 11 May 2014, 16:58 last edited by
[quote author="mcwork" date="1399824479"]The link you suggest is for QWidget, mine relates to QWindow. It is "here":http://qt-project.org/doc/qt-5/qwindow.html#close:
Both inherit QObjects, but are in different branches of the inheritance tree.So, it appears that for QWindow::close() does something very similar to "delete".[/quote]
Nope, it doesn't at all. Those are two completely different things! The delete operator destroys an Object that was allocated on the heap (i.e. via "new" operator). This will call the Object's destructor and finnally release the memory occupied by that Object. That's standard C++ stuff, not specific to Qt at all.
At the same, the close() is just a "normal" function. Indeed, it behaves a little bit different in QWindow than it does in QWidget. But if you read the docs for QWindow::close() carefully, you will see that this function does not destroy the QWindow object! It just calls the QWindow::destory() function. That is something completely different from delete'ing the QWindow object! And the QWindow::destory() function does the following, according to the docs:
Releases the native platform resources associated with this window.
Hence, after calling QWindow::destory() the "native platform resources" associated with this window have been released, but the QWindow object itself still exists! Neither has this object been removed from the Heap nor has its destructor been called - as opposed to delete'ing the Object.
__
[quote]This is very important, even though there are the ‘two things to consider’ you mentioned. Indeed this mechanism is a backup for the cases in which we forget to delete something, and ensures that our program cannot be harmful to others’, even in case of bugs, after its closing.
I will adopt this suggestion, but I also will know that for fast pieces of code one could just allocate what he needs and let the OS make the free actions that are mandatory to leave the system clean from our stuff (like your example posted yesterday)[/quote]
Please understand that when your process terminates, the OS does not destroy your pending objects for you! It just extinguishes your complete process, so that process can no longer occupy any memory. However the destructors of your pending objects will never get called! So these objects will never get a chance to perform their pending "clean up" tasks. For example, if an object would normally save some data in its destructor, this data will simply be lost! Or if the object would normally delete some temporary files in its destructor, these files will remain on the HDD. And so on. It's just not a good idea to leave pending objects when your program terminates.
Furthermore: The memory leak that results from not destroying the QApplication object in your main() function might be "harmless". That's because the process is going to terminate very soon anyway. But other memory leaks are not "harmless"! The memory leak can add up over time. And eventually your application may crash with "out of memory" error...
-
wrote on 11 May 2014, 19:55 last edited by
ok.
Thanks again.
1/14