Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [Solved] QWidget assumes allocation on heap, not stack?
Forum Updated to NodeBB v4.3 + New Features

[Solved] QWidget assumes allocation on heap, not stack?

Scheduled Pinned Locked Moved General and Desktop
11 Posts 5 Posters 8.2k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    RickH
    wrote on last edited by
    #1

    I bought the Blanchette and Summerfield book, so my questions should get fewer. But I still am unclear about this parent object business.

    Does the design assume that the objects are allocated on the heap? I guess I could just not assign a parent if the object is allocated on the stack. But the design draws conclusions from the lack of a parent. Like that the widget is a top-level window.

    I have a situation where I have one QObject aggregated into another -- a QThread derivative is a member of a QCoreApplication derivative. I assume in that case I would leave the QThread's parent NULL? Even though in fact the QCoreApplication is its parent.

    When I look at this -- http://doc.troll.no/4.5/objecttrees.html -- I worry because in the case that the parent is defined second, it seems to me that the parent would not just run the child's destructor, but would actually call delete on the child. The parent can't know how the child was allocated, right?

    Any light appreciated.

    1 Reply Last reply
    0
    • D Offline
      D Offline
      dbzhang800
      wrote on last edited by
      #2

      what do you mean by this:

      bq. I assume in that case I would leave the QThread’s parent NULL? Even though in fact the QCoreApplication is its parent.

      An Object's parent can only be set through
      @QObject( QObject * parent = 0 )@
      @void QObject::setParent ( QObject * parent )@

      If you leave the Thread's parent NULL, then it does not have an parent.

      1 Reply Last reply
      0
      • G Offline
        G Offline
        giesbert
        wrote on last edited by
        #3

        [quote author="RickH" date="1313373180"]When I look at this -- http://doc.troll.no/4.5/objecttrees.html -- I worry because in the case that the parent is defined second, it seems to me that the parent would not just run the child's destructor, but would actually call delete on the child. The parent can't know how the child was allocated, right? [/quote]

        Regardless how you create an object, if it gets a parent, the parent will try to remove it from memory by calling delete, which will implicitly call the destructor. This is by design and will always happen to child objects, if the parent is deleted.

        If you create an object on the heap (or as plain member of a class) you MUST NOT set it a parent, as the memory would then be freed 2 times (by stack and parent).

        Nokia Certified Qt Specialist.
        Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

        1 Reply Last reply
        0
        • D Offline
          D Offline
          dbzhang800
          wrote on last edited by
          #4

          Object allocated on stack can be given a parent as long as you can guarantee that it will be destroyed before it's parent.

          And we can see many code like this:
          @
          void MainWindow::xxxxx(...)
          {
          QDialog dlg(this);
          dlg.exec();
          ...
          }
          @

          1 Reply Last reply
          0
          • G Offline
            G Offline
            giesbert
            wrote on last edited by
            #5

            Ok, that's correct.
            For this case it works, but you MUST have the guarantee, otherwise you get unexpected results.

            Nokia Certified Qt Specialist.
            Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

            1 Reply Last reply
            0
            • R Offline
              R Offline
              RickH
              wrote on last edited by
              #6

              In the case that Hobby mentioned, does MainWindow call delete on dlg? What happens if you call delete on an object allocated on the stack?

              Ohhhhhh. It just hit me. Is it that when dlg is deleted, its destructor tells the MainWindow it is ceasing to exist, and the MainWindow removes it from its list of children? Then when the MainWindow is deleted, it doesn't call delete on the child. Right?

              1 Reply Last reply
              0
              • L Offline
                L Offline
                loladiro
                wrote on last edited by
                #7

                [quote]
                Ohhhhhh. It just hit me. Is it that when dlg is deleted, its destructor tells the MainWindow it is ceasing to exist, and the MainWindow removes it from its list of children? Then when the MainWindow is deleted, it doesn’t call delete on the child. Right?
                [/quote]
                Correct :)

                However NEVER do this:
                @
                MainWindows *w = new MainWindow;
                Dialog d(w);
                delete w;
                @

                1 Reply Last reply
                0
                • G Offline
                  G Offline
                  giesbert
                  wrote on last edited by
                  #8

                  [quote author="RickH" date="1313403794"]In the case that Hobby mentioned, does MainWindow call delete on dlg? What happens if you call delete on an object allocated on the stack? [/quote]

                  Then you get exceptions. AFAIK, officially, the behavior is undefined :-)
                  If a QObject is destroyed, it tells it's parent about the fact and then the parent removes it from the list of children.

                  Nokia Certified Qt Specialist.
                  Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                  1 Reply Last reply
                  0
                  • G Offline
                    G Offline
                    goetz
                    wrote on last edited by
                    #9

                    [quote author="RickH" date="1313403794"]What happens if you call delete on an object allocated on the stack?[/quote]

                    In general:

                    @
                    void myFunction()
                    {
                    MyObject obj;
                    // do something
                    delete &obj; // this works
                    // do something more
                    } // it crashes here
                    @

                    The call in line 5 is ok execution wise. It calls the destructor of the MyObject class held in variable pointer. The catastrophe starts at the end of the function (end of the variable scope of obj, actually). Because obj is created on the stack, the compiler calls the destructor again. As the object is already destroyed, this will fail and you are very, very likely to having your program crash.

                    Specific to QObjects:

                    @
                    void myFucntion()
                    {
                    QObject *parentObject = new QObject;
                    QObject childObject(&parentObject);
                    // do your work here
                    delete parentObject; // you need this to prevent a memory leak!
                    } // bang! on childObject
                    @

                    The above code seems ok, but it will crash on the exit of the function too. You must delete the parentObject, because it's created on the heap and you have a memory leak otherwise. But due to the parent-child relationship, the destructor of parentObject calls the destructor of childObject, effectively resulting in a "delete &childObject". From this point on the same catastrophe is on its way as in the first example, because the compiler generated a call on childObject's constructor at the end of the function.

                    You can mix stack/heap allocation and set the parent of a stack-allocated object. But you must make absolutely sure that the stack-allocated object is destroyed before the parent object! This is insofar non-critical, because if a OQbject tells its parent that it no longer is living and the parent removes it from its list of children then.

                    As a rule of thumb: If in doubt use heap allocation with new and explicitly call delete.

                    http://www.catb.org/~esr/faqs/smart-questions.html

                    1 Reply Last reply
                    0
                    • R Offline
                      R Offline
                      RickH
                      wrote on last edited by
                      #10

                      Interesting discussion.

                      So in my case of one QObject derivative being a member of another QObject derivative:

                      @QCoreAppDeriv : public QCoreApplication {
                      QThreadDeriv myThread;
                      :
                      }@

                      The way C++ is set up, the destructor for the object-as-a-whole is called before the destructors for the objects-who-are-members. So I have to not set the parent of the member to be the object-as-a-whole. If I do, the object-as-a-whole will call delete on the member.

                      1 Reply Last reply
                      0
                      • G Offline
                        G Offline
                        goetz
                        wrote on last edited by
                        #11

                        [quote author="RickH" date="1313418131"]
                        The way C++ is set up, the destructor for the object-as-a-whole is called before the destructors for the objects-who-are-members. So I have to not set the parent of the member to be the object-as-a-whole. If I do, the object-as-a-whole will call delete on the member.
                        [/quote]

                        Yes, that's correct.
                        And the destructor fthe object-as-a-whole will be ran before the destructors of the members.

                        If you need parent-child relationship in this use case, use a pointer and new instead of an object variable.

                        http://www.catb.org/~esr/faqs/smart-questions.html

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved