[Interest] Double destruction of Qt objects in Qt example code?

K. Frank kfrank29.c at gmail.com
Sun Aug 19 01:29:08 CEST 2012


Hello Nikos!

On Sat, Aug 18, 2012 at 2:29 PM, Nikos Chantziaras <realnc at gmail.com> wrote:
> On 18/08/12 20:46, K. Frank wrote:
>> [...]
>> This does raise one c++ / Qt question for me:  When an automatic
>> variable goes out of scope, its destructor is called (and, at some
>> point, the stack is popped, but not by the destructor nor by any
>> explicit user code).  When a heap variable is deleted, its destructor
>> is called, and the equivalent of free is called.  The point is delete
>> is not called (in correct code) on automatic variables.
>>
>> How can the Qt parent-child system work with both automatic and
>> heap variables as children?  When a child object registers itself
>> with its parent (e.g., by being passed a pointer to its parent in its
>> constructor), neither the child object nor the parent knows whether
>> the child is an automatic or heap variable (and, using portable
>> standard c++, can't know).  So how can the parent know (when the
>> parent is destroyed) whether to call the child's destructor directly or
>> to call delete on the child?
>
> Qt doesn't detect this.  Your application will crash.  So don't do it :-)

Yes, I agree.

I think I see my point of confusion.  The "Object Trees & Ownership"
article you linked to in the documentation:

   http://doc-snapshot.qt-project.org/4.8/objecttrees.html#construction-destruction-order-of-qobjects

is slightly misleading.

Quoting from the end of the article:

   But now consider what happens if we swap the order of construction,
   as shown in this second snippet:

      int main()
      {
          QPushButton quit("Quit");
          QWidget window;

          quit.setParent(&window);
          ...
      }

   In this case, the order of destruction causes a problem. The parent's
   destructor is called first because it was created last. It then calls the
   destructor of its child, quit, which is incorrect because quit is a local
   variable. When quit subsequently goes out of scope, its destructor is
   called again, this time correctly, but the damage has already been done.

This code is indeed wrong, but the explanation is not as sharp as it could
be.  Quoting again:

   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.
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.

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.

Thanks again.


K. Frank



More information about the Interest mailing list