Am 19.08.12 01:29, schrieb K. Frank: > ... > It then calls the destructor of its child, quit, which is incorrect > because quit is a local variable. > > To be more precise, it ought to say is "It then calls delete on its child ..." > As I understand c++, it is technically legal -- for the time being -- to call > the destructor of a local variable, although an error will occur later when > the local variable goes out of scope and is destroyed a second time.
Wow - I did not even know that it was legal C++ to explicitly call a d'tor, as in: SomeObject someObject; someObject.~SomeObject(); (at least my gcc on Mac compiles this without complaint. And as long as you don't release any resources twice inside the d'tor - or simply have a qDebug("D'tor called.") or something in the d'tor - nothing bad happens: the d'tor is indeed simply called twice (once explicitly, once the automatic variable goes out of scope). However it never occured to me to actually try such a thing. I mean, what would be a practical scenario where one wanted to explicitly call a d'tor? So clean up resources before the actual object gets destroyed (assuming that the code inside the d'tor would take care not to delete resources twice, such that it would be okay to call a d'tor several times)? So when I read something like "...it then calls the destructor of its child..." my brain automatically transmogrifies this into "... it then calls delete of its child ...". But you are right, given the fact that it actually /is/ legal C++ - and semantically different from calling delete on an object - to explicitly call a d'tor, the above is not quite right (but I'm 99% sure that what is really meant here that delete is called upon the child, because calling a d'tor directly doesn't make any sense to me). > However, it is not legal to call delete on a local (non-new'ed) variable, > and the error occurs right when delete is called, rather than later when > the variable goes out of scope. Just to be precise: it /is/ legal C++ to call delete on a stack variable, at least in the syntactical sense: SomeObject someObject; // allocated on the stack delete &someObject; // does complain just fine My gcc on Mac did not even issue a big fat warning with the standard qmake settings, but not surprisingly above code crashes immediatelly at that point, just as K. Frank said: error for object 0x7fff5fbff7cf: pointer being freed was not allocated > A minor point, but the wording got me analyzing things not quite as > precisely as I should have. > >> On a similar note, don't delete QObject instances manually. Call their >> deleteLater() member function instead. > > Yes, well worth remembering that deleteLater() is available. I think as a rule of thumb one could say that for objects (and their children) such as dialogs, Qt collection types and probably most other Qt classes it is fine to call delete (immediate deallocation), as long as you allocated (new) them yourself. Or in other words: you have to be careful (and read the docs) with objects allocated by Qt itself: sometimes Qt indeed still wants to do some tasks with those objects after it has "handed them to you for inspection" when it goes back to the event queue - and then you *need* to call deleteLater() on them (instead of delete). One concrete example I know of is the QNetworkReply created inside the Qt event queue (once a network packet or some other network related event has happened), passed to your code, and you must call deleteLater on it: http://qt-project.org/doc/qt-4.8/qnetworkaccessmanager.html#finished Then there is one API which explicitly requests that the argument you have to pass be allocated on the heap, because Qt takes ownership of that object and deletes it later on (with delete). But I cannot remember which class that was, I thought also the QNetworkAccessManager, or maybe somewhere in the multithreading departement... By the way it can be very useful to call delete on a QObject, even if that object has a valid parent (which would delete all its children later on, once that parent gets deleted). For instance if you allocate a dialog on the heap (*), you typically pass the window from which that dialog was called as parent (as a side effect, the dialog is then also centered in the parent window/dialog). You might think you're done, no delete ever necessary on your side, because that object has a valid parent which will eventually take care of it! Now if that parent happens to be the QMainWindow, the child dialogs won't get deleted until the very end of the application lifecycle. And they eat up memory (think "file dialog"). Technically /not/ a memory leak, as the parent QMainWindow still references them (and deletes them properly when it gets itself deleted). So you should call delete on those dialogs (or whatever Qt objects), once the user has made the decision and pressed either OK or Cancel. As we have seen calling delete is absolutely fine, because the child will "unregister" itself from its parent. Cheers, Oliver (*) This very scenario is one reason why people argue you should allocate (file) dialogs etc. on the stack, such that they automatically get deallocated when not needed anymore. I won't go into any more details here, but if you want to indulge yourself with more "heap vs stack allocation" discussions, go back into the Qt archive, e.g. here: http://lists.trolltech.com/qt-interest/2007-08/thread00403-0.html :) _______________________________________________ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest