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. Resource management in Qt

Resource management in Qt

Scheduled Pinned Locked Moved Unsolved General and Desktop
20 Posts 8 Posters 3.9k Views 6 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.
  • tomyT Offline
    tomyT Offline
    tomy
    wrote on last edited by aha_1980
    #1

    Hi all,

    In modern C++, we no longer use the raw new operator to grasp memory from heap, but use smart pointers for that purpose, to prevent memory leak. I have doubt if Qt uses merely this way, too.

    We've created a custom widget like this:

    Test.h:

    #ifndef TEST_H
    #define TEST_H
    #include <QDialog>
    
    class QLineEdit;
    class QPushButton;
    
    class Test : public QDialog
    {
        Q_OBJECT
    
    public:
        Test(QWidget* parent = nullptr);
    
    private:
        QLineEdit* line;
        QPushButton* quit;
    
    };
    
    #endif // TEST_H
    

    Test.cpp:

    #include <QLineEdit>
    #include <QPushButton>
    #include <QVBoxLayout>
    #include "test.h"
    
    Test::Test(QWidget* parent): QDialog(parent = nullptr)
    {
      line = new QLineEdit;
      quit = new QPushButton(tr("Quit"));
    
      connect(quit, &QPushButton::clicked, this, &Test::close);
    
      QVBoxLayout* layout = new QVBoxLayout();
    
      layout->addWidget(line);
      layout->addWidget(quit);
      setLayout(layout);
    }
    

    main.cpp:

    #include<QApplication>
    #include "test.h"
    
    int main(int argc, char* argv[])
    {
        QApplication app(argc, argv);
        Test* t = new Test;
        t->show();
    
        return app.exec();
    }
    

    As you know, our custom widget is independent, because of Test::Test(QWidget* parent): QDialog(parent = nullptr), and we've allocated dynamic memory for a QLineEdit and a QPushButton.
    We've defined no destructor and even a default one is created by the compiler, it's useless here because can't release the memory grasped by raw new. We here have two memory leak, haven't we?

    In the main.cpp too, we've created an instance of the class by new. This is to me another leak.

    What does Qt offer for these, please?

    aha_1980A W 2 Replies Last reply
    1
    • tomyT tomy

      Hi all,

      In modern C++, we no longer use the raw new operator to grasp memory from heap, but use smart pointers for that purpose, to prevent memory leak. I have doubt if Qt uses merely this way, too.

      We've created a custom widget like this:

      Test.h:

      #ifndef TEST_H
      #define TEST_H
      #include <QDialog>
      
      class QLineEdit;
      class QPushButton;
      
      class Test : public QDialog
      {
          Q_OBJECT
      
      public:
          Test(QWidget* parent = nullptr);
      
      private:
          QLineEdit* line;
          QPushButton* quit;
      
      };
      
      #endif // TEST_H
      

      Test.cpp:

      #include <QLineEdit>
      #include <QPushButton>
      #include <QVBoxLayout>
      #include "test.h"
      
      Test::Test(QWidget* parent): QDialog(parent = nullptr)
      {
        line = new QLineEdit;
        quit = new QPushButton(tr("Quit"));
      
        connect(quit, &QPushButton::clicked, this, &Test::close);
      
        QVBoxLayout* layout = new QVBoxLayout();
      
        layout->addWidget(line);
        layout->addWidget(quit);
        setLayout(layout);
      }
      

      main.cpp:

      #include<QApplication>
      #include "test.h"
      
      int main(int argc, char* argv[])
      {
          QApplication app(argc, argv);
          Test* t = new Test;
          t->show();
      
          return app.exec();
      }
      

      As you know, our custom widget is independent, because of Test::Test(QWidget* parent): QDialog(parent = nullptr), and we've allocated dynamic memory for a QLineEdit and a QPushButton.
      We've defined no destructor and even a default one is created by the compiler, it's useless here because can't release the memory grasped by raw new. We here have two memory leak, haven't we?

      In the main.cpp too, we've created an instance of the class by new. This is to me another leak.

      What does Qt offer for these, please?

      aha_1980A Offline
      aha_1980A Offline
      aha_1980
      Lifetime Qt Champion
      wrote on last edited by
      #2

      @tomy

      You have two possibilities:

      1. Use the *parent parameter of each QObject to define a tree structure: https://doc.qt.io/qt-5/objecttrees.html
      2. Use the shared/unique/... pointers from STL or Qt to manage object lifecycles. In that case, don't give a parent.

      Regards

      Qt has to stay free or it will die.

      tomyT 1 Reply Last reply
      1
      • aha_1980A aha_1980

        @tomy

        You have two possibilities:

        1. Use the *parent parameter of each QObject to define a tree structure: https://doc.qt.io/qt-5/objecttrees.html
        2. Use the shared/unique/... pointers from STL or Qt to manage object lifecycles. In that case, don't give a parent.

        Regards

        tomyT Offline
        tomyT Offline
        tomy
        wrote on last edited by tomy
        #3

        @aha_1980

        1. Use the *parent parameter of each QObject to define a tree structure: https://doc.qt.io/qt-5/objecttrees.html

        So if we use the constructor the following way, the widget's still dependent on its parent (QDialog):

        public:
            Test();
        ...
        

        And it's destroyed, and all resources are released, when the program closes. But that mightn't be proper always!

        For example, consider a program running for 5 hours. In its first hour, it creates a number of objects using new (from heap), then goes for other sections and leaves them out, useless for the rest (four hours). Memory leak!

        1. Use the shared/unique/... pointers from STL or Qt to manage object lifecycles. In that case, don't give a parent.

        Now, to prevent the leaks above, if we give a parent = nullptr, to use a unique pointer from STL:

        std::unique_ptr<QPushButton> quit(new QPushButton);
        

        I get errors!

        I also think use of smart pointers the way it's done in std C++ is simpler than the way it's handled by Qt.

        sierdzioS 1 Reply Last reply
        0
        • tomyT tomy

          @aha_1980

          1. Use the *parent parameter of each QObject to define a tree structure: https://doc.qt.io/qt-5/objecttrees.html

          So if we use the constructor the following way, the widget's still dependent on its parent (QDialog):

          public:
              Test();
          ...
          

          And it's destroyed, and all resources are released, when the program closes. But that mightn't be proper always!

          For example, consider a program running for 5 hours. In its first hour, it creates a number of objects using new (from heap), then goes for other sections and leaves them out, useless for the rest (four hours). Memory leak!

          1. Use the shared/unique/... pointers from STL or Qt to manage object lifecycles. In that case, don't give a parent.

          Now, to prevent the leaks above, if we give a parent = nullptr, to use a unique pointer from STL:

          std::unique_ptr<QPushButton> quit(new QPushButton);
          

          I get errors!

          I also think use of smart pointers the way it's done in std C++ is simpler than the way it's handled by Qt.

          sierdzioS Offline
          sierdzioS Offline
          sierdzio
          Moderators
          wrote on last edited by
          #4

          @tomy said in Resource management in Qt:

          For example, consider a program running for 5 hours. In its first hour, it creates a number of objects using new (from heap), then goes for other sections and leaves them out, useless for the rest (four hours). Memory leak!

          If you have a widget that is being displayed (or not, when you call setVisible(false) on it), it is used memory. It does not matter if the user of your program clicks on anything or not, and it does not matter how long the application is open. It is not a memory leak.

          However, if you have a widget and close it, but you don't free the memory because you set the parent-child architecture wrongly - then it is a memory leak indeed, but it's your bug, not Qt fault.

          std::unique_ptr<QPushButton> quit(new QPushButton);

          It helps when you write correct code ;-)

          auto quit = std::make_unique<QPushButton>();

          (Z(:^

          1 Reply Last reply
          3
          • mrjjM Offline
            mrjjM Offline
            mrjj
            Lifetime Qt Champion
            wrote on last edited by mrjj
            #5

            Hi
            Something like
            std::unique_ptr<QPushButton> quit=make_unique<QPushButton>();
            But there is one cavecat.
            If you use an std::unique_ptr, for your widget, you cannot insert into anything.
            Since if assign a parent, you get double delete.

            Having each widget in its own std::unique_ptr would be overkill.
            Qt current system where one parent/owner delete all sub children makes a cleaner syntax and far less fuss using the children.

            QDialog have an option for
            diag->setAttribute(Qt::WA_DeleteOnClose);
            Which means as soon as the user closes it, it will deallocate itself and all children.
            So it's possible to tweak how fast you want memory back.

            1 Reply Last reply
            3
            • tomyT Offline
              tomyT Offline
              tomy
              wrote on last edited by
              #6

              I'm confused! Seemingly that parent-child relationship of Qt is solely for collecting memory leaks. Well, good, if so. Then how does Qt this way want to follow C++'s progress, for instance those smart pointers!?

              Using merely raw memory allocation, using new, and relying on Qt's parent-child relationship and wanting no to have any memory leak is error-prone and difficult to cope with, properly completely. Smart pointers are the remedy.

              By the way, I get these errors. Quite possibly I need to include some library.

              0_1559396663823_Untitled.png

              sierdzioS 1 Reply Last reply
              0
              • tomyT tomy

                I'm confused! Seemingly that parent-child relationship of Qt is solely for collecting memory leaks. Well, good, if so. Then how does Qt this way want to follow C++'s progress, for instance those smart pointers!?

                Using merely raw memory allocation, using new, and relying on Qt's parent-child relationship and wanting no to have any memory leak is error-prone and difficult to cope with, properly completely. Smart pointers are the remedy.

                By the way, I get these errors. Quite possibly I need to include some library.

                0_1559396663823_Untitled.png

                sierdzioS Offline
                sierdzioS Offline
                sierdzio
                Moderators
                wrote on last edited by
                #7

                @tomy said in Resource management in Qt:

                Seemingly that parent-child relationship of Qt is solely for collecting memory leaks. Well, good, if so.

                What? No, meory leak prevention is not the main objective of this system. Parent-child trees also help widgets properly paint (within other widgets - to build complex UIs).

                Then how does Qt this way want to follow C++'s progress, for instance those smart pointers!?

                You can join that discussion on Qt development mailing list, Qt 6 is being discussed as we speak, and smart pointers are part of that discussion as well (as is the future of Qt smart pointers: QPointer, QSharedPointer, QWeakPointer etc.)

                Using merely raw memory allocation, using new, and relying on Qt's parent-child relationship and wanting no to have any memory leak is error-prone and difficult to cope with, properly completely. Smart pointers are the remedy.

                Have you ever actually used std::unique_ptr? While it is indeed a great thing, but also "difficult to cope with" describes it neatly :-) in my opinion.

                Using QPointer and parent-child for UI elements is very easy and perfectly safe from leaks. In all other parts of apps - indeed, smart pointers should be used. There is nothing wrong in using best thing from both worlds, in one app :-) Anyway, if you have a good suggestion how to change Qt to use std smart pointers without breaking thousands of applications using Qt already, people on the mailing list will be glad to hear it.

                (Z(:^

                tomyT 1 Reply Last reply
                5
                • tomyT tomy

                  Hi all,

                  In modern C++, we no longer use the raw new operator to grasp memory from heap, but use smart pointers for that purpose, to prevent memory leak. I have doubt if Qt uses merely this way, too.

                  We've created a custom widget like this:

                  Test.h:

                  #ifndef TEST_H
                  #define TEST_H
                  #include <QDialog>
                  
                  class QLineEdit;
                  class QPushButton;
                  
                  class Test : public QDialog
                  {
                      Q_OBJECT
                  
                  public:
                      Test(QWidget* parent = nullptr);
                  
                  private:
                      QLineEdit* line;
                      QPushButton* quit;
                  
                  };
                  
                  #endif // TEST_H
                  

                  Test.cpp:

                  #include <QLineEdit>
                  #include <QPushButton>
                  #include <QVBoxLayout>
                  #include "test.h"
                  
                  Test::Test(QWidget* parent): QDialog(parent = nullptr)
                  {
                    line = new QLineEdit;
                    quit = new QPushButton(tr("Quit"));
                  
                    connect(quit, &QPushButton::clicked, this, &Test::close);
                  
                    QVBoxLayout* layout = new QVBoxLayout();
                  
                    layout->addWidget(line);
                    layout->addWidget(quit);
                    setLayout(layout);
                  }
                  

                  main.cpp:

                  #include<QApplication>
                  #include "test.h"
                  
                  int main(int argc, char* argv[])
                  {
                      QApplication app(argc, argv);
                      Test* t = new Test;
                      t->show();
                  
                      return app.exec();
                  }
                  

                  As you know, our custom widget is independent, because of Test::Test(QWidget* parent): QDialog(parent = nullptr), and we've allocated dynamic memory for a QLineEdit and a QPushButton.
                  We've defined no destructor and even a default one is created by the compiler, it's useless here because can't release the memory grasped by raw new. We here have two memory leak, haven't we?

                  In the main.cpp too, we've created an instance of the class by new. This is to me another leak.

                  What does Qt offer for these, please?

                  W Offline
                  W Offline
                  wrosecrans
                  wrote on last edited by
                  #8

                  @tomy said in Resource management in Qt:

                  In modern C++, we no longer use the raw new operator to grasp memory from heap, but use smart pointers for that purpose, to prevent memory leak.

                  That's an oversimplification. Imagine you have a generic node graph. You have a std::shared_ptr to a Graph. The Graph has a vector of std::shared_ptr's to Nodes, and Nodes can have std::shared_ptrs to each other.

                  When you are done with a graph, you make the shared_ptr go out of scope, and the Graph's destructor executes. It ends the lifetime for the vector of shared_ptr's to the nodes, and they all have their ref counts decremented. But, many of the Nodes themselves have shared_ptrs to each other, so it doesn't decrement the ref count to 0.

                  Now, you have a web of Node objects in memory that haven't been destructed or their memory reclaimed, but you have now way to reach any of them! Oh no, smart pointers didn't save us, and we still have a memory leak! We still needed to think through an owning relationship (Like calling the graph the "parent" of the Nodes, and making it responsible for freeing the Nodes regardless of refcounts...) to be certain of what happens.

                  Smart pointers are a tool. A useful tool. But not magic, and they don't relieve you from having to think about ownership and responsibilities when it comes to memory allocation and management. And smart pointers don't make "new" a dirty word. You just have to understand how the API's you are using work, and use the right tool for the right job.

                  kshegunovK 1 Reply Last reply
                  5
                  • Chris KawaC Online
                    Chris KawaC Online
                    Chris Kawa
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    We had a discussion about it some 3 years ago.

                    The gist of it is anything that takes ownership of some resource and releases it is a type of smart pointer. It doesn't have to have "smart" or "pointer" in the name. Having said that there's not much difference between this:

                    auto owner = std::make_unique<QPushButton>();
                    

                    and this:

                    new QPushButton(parent);
                    

                    In the first case owner deletes the button when it is deleted itself. In the second case same thing happens - button is deleted by the parent when it is deleted itself. From memory management perspective that's exactly the same thing. QObjects are sort of a smart pointers for their children.

                    1 Reply Last reply
                    7
                    • W wrosecrans

                      @tomy said in Resource management in Qt:

                      In modern C++, we no longer use the raw new operator to grasp memory from heap, but use smart pointers for that purpose, to prevent memory leak.

                      That's an oversimplification. Imagine you have a generic node graph. You have a std::shared_ptr to a Graph. The Graph has a vector of std::shared_ptr's to Nodes, and Nodes can have std::shared_ptrs to each other.

                      When you are done with a graph, you make the shared_ptr go out of scope, and the Graph's destructor executes. It ends the lifetime for the vector of shared_ptr's to the nodes, and they all have their ref counts decremented. But, many of the Nodes themselves have shared_ptrs to each other, so it doesn't decrement the ref count to 0.

                      Now, you have a web of Node objects in memory that haven't been destructed or their memory reclaimed, but you have now way to reach any of them! Oh no, smart pointers didn't save us, and we still have a memory leak! We still needed to think through an owning relationship (Like calling the graph the "parent" of the Nodes, and making it responsible for freeing the Nodes regardless of refcounts...) to be certain of what happens.

                      Smart pointers are a tool. A useful tool. But not magic, and they don't relieve you from having to think about ownership and responsibilities when it comes to memory allocation and management. And smart pointers don't make "new" a dirty word. You just have to understand how the API's you are using work, and use the right tool for the right job.

                      kshegunovK Offline
                      kshegunovK Offline
                      kshegunov
                      Moderators
                      wrote on last edited by
                      #10

                      @wrosecrans said in Resource management in Qt:

                      Smart pointers are a tool. A useful tool.

                      A tool that, sadly, many people, based on the recommendations of few people, have decided is the ultimate way to manage memory. And to make it worse they're willing to jump hoops to make it work, even if not warranted (neither the first time, nor the last - yes, singletons are such a case). Clear ownership is always going to rule supreme; no smart pointer (which isn't even a pointer[1]) can substitute.

                      [1]: We call stack objects that manage a pointer "smart pointers", but in fact they're not. They are objects, and they are allocated with automatic storage duration.

                      But not magic, and they don't relieve you from having to think about ownership and responsibilities when it comes to memory allocation and management. And smart pointers don't make "new" a dirty word. You just have to understand how the API's you are using work, and use the right tool for the right job.

                      Amen brother!

                      Read and abide by the Qt Code of Conduct

                      1 Reply Last reply
                      5
                      • sierdzioS sierdzio

                        @tomy said in Resource management in Qt:

                        Seemingly that parent-child relationship of Qt is solely for collecting memory leaks. Well, good, if so.

                        What? No, meory leak prevention is not the main objective of this system. Parent-child trees also help widgets properly paint (within other widgets - to build complex UIs).

                        Then how does Qt this way want to follow C++'s progress, for instance those smart pointers!?

                        You can join that discussion on Qt development mailing list, Qt 6 is being discussed as we speak, and smart pointers are part of that discussion as well (as is the future of Qt smart pointers: QPointer, QSharedPointer, QWeakPointer etc.)

                        Using merely raw memory allocation, using new, and relying on Qt's parent-child relationship and wanting no to have any memory leak is error-prone and difficult to cope with, properly completely. Smart pointers are the remedy.

                        Have you ever actually used std::unique_ptr? While it is indeed a great thing, but also "difficult to cope with" describes it neatly :-) in my opinion.

                        Using QPointer and parent-child for UI elements is very easy and perfectly safe from leaks. In all other parts of apps - indeed, smart pointers should be used. There is nothing wrong in using best thing from both worlds, in one app :-) Anyway, if you have a good suggestion how to change Qt to use std smart pointers without breaking thousands of applications using Qt already, people on the mailing list will be glad to hear it.

                        tomyT Offline
                        tomyT Offline
                        tomy
                        wrote on last edited by
                        #11

                        @sierdzio

                        meory leak prevention is not the main objective of this system

                        Up to now, I don't think Qt's parent-child mechanism is completely successful in that objective, because the resources are mainly freed when the project closes. While modern OSes do the same task after closing the program, making Qt's work actually useless in effect.

                        QPointer also is apparently successful only in preventing dangling pointers and it is different from memory leak.

                        Have you ever actually used std::unique_ptr?

                        No, not yet. How about you? ;)

                        Let me ask you this question,please. How best do you write a parented project like this:

                        test.h:

                        #include <QDialog>
                        
                        class QLineEdit;
                        class QSpinBox;
                        class QFormLayout;
                        
                        class Test : public QDialog
                        {
                            Q_OBJECT
                        
                        public:
                            Test(QWidget* parent = nullptr);
                            void do_something_else();
                        
                        private:
                            QFormLayout* formLayout;
                            QLineEdit* nameLineEdit;
                            QSpinBox* ageSpinBox;
                        };
                        

                        test.cpp:

                        Test::Test(QWidget* parent): QDialog(parent)
                        {
                            formLayout = new QFormLayout;
                            nameLineEdit = new QLineEdit;
                            ageSpinBox = new QSpinBox;
                        
                            formLayout->addRow(tr("&Name:"), nameLineEdit);
                            formLayout->addRow(tr("&Age:"), ageSpinBox);
                            setLayout(formLayout);
                        
                            do_something_else();
                        }
                        
                        void Test::do_something_else() {
                        
                            // Accomplish some other task for several hours
                        }
                        
                        Chris KawaC sierdzioS 2 Replies Last reply
                        0
                        • tomyT tomy

                          @sierdzio

                          meory leak prevention is not the main objective of this system

                          Up to now, I don't think Qt's parent-child mechanism is completely successful in that objective, because the resources are mainly freed when the project closes. While modern OSes do the same task after closing the program, making Qt's work actually useless in effect.

                          QPointer also is apparently successful only in preventing dangling pointers and it is different from memory leak.

                          Have you ever actually used std::unique_ptr?

                          No, not yet. How about you? ;)

                          Let me ask you this question,please. How best do you write a parented project like this:

                          test.h:

                          #include <QDialog>
                          
                          class QLineEdit;
                          class QSpinBox;
                          class QFormLayout;
                          
                          class Test : public QDialog
                          {
                              Q_OBJECT
                          
                          public:
                              Test(QWidget* parent = nullptr);
                              void do_something_else();
                          
                          private:
                              QFormLayout* formLayout;
                              QLineEdit* nameLineEdit;
                              QSpinBox* ageSpinBox;
                          };
                          

                          test.cpp:

                          Test::Test(QWidget* parent): QDialog(parent)
                          {
                              formLayout = new QFormLayout;
                              nameLineEdit = new QLineEdit;
                              ageSpinBox = new QSpinBox;
                          
                              formLayout->addRow(tr("&Name:"), nameLineEdit);
                              formLayout->addRow(tr("&Age:"), ageSpinBox);
                              setLayout(formLayout);
                          
                              do_something_else();
                          }
                          
                          void Test::do_something_else() {
                          
                              // Accomplish some other task for several hours
                          }
                          
                          Chris KawaC Online
                          Chris KawaC Online
                          Chris Kawa
                          Lifetime Qt Champion
                          wrote on last edited by
                          #12

                          @tomy said in Resource management in Qt:

                          Up to now, I don't think Qt's parent-child mechanism is completely successful in that objective, because the resources are mainly freed when the project closes.

                          That's not at all true. The resources are released whenever you release them. It has nothing to do with smart pointers or parent child relation. There's no automatic garbage collection or anything like that. As was said above, you as a designer decide when objects are created and destroyed. If you don't want an object to exist just delete it. Qt doesn't dictate whether you create an object on a stack or a heap. You can delete it whenever you see fit. The parent child relation just lets you conveniently delete the top level object and it will clean all of its children, but you can manually delete them at any point before that if you want.

                          As to your example - that's just poorly designed code. Nothing to do with Qt. If you want a long lasting task to run and you don't want the dialog to stick around then structure your program like that. Certainly don't run tasks lasting several hours in a blocking call in ui thread. That's just bad.

                          You can do it like this for example:

                          class Whatever
                          {
                             TaskSettings get_task_settings() {
                                  SomeSettingsDialog dialog;
                                  dialog.exec();
                                  return dialog.settings();
                             }
                          
                             void do_something_else {
                                   TaskSettings settings = get_task_settings();
                                   StartTaskInAnotherThread(settings);
                                   //and exit immediately
                             }
                          }
                          

                          Nothing is leaked, no dialog resources are held longer than needed, no smart pointers or otherwise.

                          tomyT 1 Reply Last reply
                          4
                          • Chris KawaC Chris Kawa

                            @tomy said in Resource management in Qt:

                            Up to now, I don't think Qt's parent-child mechanism is completely successful in that objective, because the resources are mainly freed when the project closes.

                            That's not at all true. The resources are released whenever you release them. It has nothing to do with smart pointers or parent child relation. There's no automatic garbage collection or anything like that. As was said above, you as a designer decide when objects are created and destroyed. If you don't want an object to exist just delete it. Qt doesn't dictate whether you create an object on a stack or a heap. You can delete it whenever you see fit. The parent child relation just lets you conveniently delete the top level object and it will clean all of its children, but you can manually delete them at any point before that if you want.

                            As to your example - that's just poorly designed code. Nothing to do with Qt. If you want a long lasting task to run and you don't want the dialog to stick around then structure your program like that. Certainly don't run tasks lasting several hours in a blocking call in ui thread. That's just bad.

                            You can do it like this for example:

                            class Whatever
                            {
                               TaskSettings get_task_settings() {
                                    SomeSettingsDialog dialog;
                                    dialog.exec();
                                    return dialog.settings();
                               }
                            
                               void do_something_else {
                                     TaskSettings settings = get_task_settings();
                                     StartTaskInAnotherThread(settings);
                                     //and exit immediately
                               }
                            }
                            

                            Nothing is leaked, no dialog resources are held longer than needed, no smart pointers or otherwise.

                            tomyT Offline
                            tomyT Offline
                            tomy
                            wrote on last edited by tomy
                            #13

                            @Chris-Kawa

                            You radically changed my code and now neither I get any new thing useful from that nor is the ambiguity of that relation more eliminated. I was reading your post of three years ago and was finding it useful.

                            Just one point is clear to me for this post: smart pointers are created for occasions we "forget" to "delete" a memory block allocated dynamically. If we can write delete whenever needed, so why are modern pointers called "smart"?

                            auto owner = std::make_unique<QPushButton>();

                            This since isn't a static member doesn't work either on my Qt Creator!
                            error: 'auto' not allowed in non-static class member

                            kshegunovK 1 Reply Last reply
                            0
                            • tomyT tomy

                              @sierdzio

                              meory leak prevention is not the main objective of this system

                              Up to now, I don't think Qt's parent-child mechanism is completely successful in that objective, because the resources are mainly freed when the project closes. While modern OSes do the same task after closing the program, making Qt's work actually useless in effect.

                              QPointer also is apparently successful only in preventing dangling pointers and it is different from memory leak.

                              Have you ever actually used std::unique_ptr?

                              No, not yet. How about you? ;)

                              Let me ask you this question,please. How best do you write a parented project like this:

                              test.h:

                              #include <QDialog>
                              
                              class QLineEdit;
                              class QSpinBox;
                              class QFormLayout;
                              
                              class Test : public QDialog
                              {
                                  Q_OBJECT
                              
                              public:
                                  Test(QWidget* parent = nullptr);
                                  void do_something_else();
                              
                              private:
                                  QFormLayout* formLayout;
                                  QLineEdit* nameLineEdit;
                                  QSpinBox* ageSpinBox;
                              };
                              

                              test.cpp:

                              Test::Test(QWidget* parent): QDialog(parent)
                              {
                                  formLayout = new QFormLayout;
                                  nameLineEdit = new QLineEdit;
                                  ageSpinBox = new QSpinBox;
                              
                                  formLayout->addRow(tr("&Name:"), nameLineEdit);
                                  formLayout->addRow(tr("&Age:"), ageSpinBox);
                                  setLayout(formLayout);
                              
                                  do_something_else();
                              }
                              
                              void Test::do_something_else() {
                              
                                  // Accomplish some other task for several hours
                              }
                              
                              sierdzioS Offline
                              sierdzioS Offline
                              sierdzio
                              Moderators
                              wrote on last edited by
                              #14

                              @tomy said in Resource management in Qt:

                              I don't think Qt's parent-child mechanism is completely successful in that objective, because the resources are mainly freed when the project closes. While modern OSes do the same task after closing the program, making Qt's work actually useless in effect.

                              As stated before - that depends solely on how you build your UI. If you have a GUI app - let's say a web browser - then obviously the UI needs to stay in memory while the application is open. Otherwise users won't see anything... and these resources need to be freed only when the whole application is being closed. There is nothing that smart pointers would change in this scenario.

                              There are parts of that app, though, that do benefit from more smartness - browser tabs. Each new tab allocates memory, and closing the tab should free that memory. With Qt's approach (parent-child), you don't have any memory leaks here: a tab is created, added to the tree. You can delete it when the tab is closed, but if you forget to do it in code, no memory will leak - Qt will "remember" to free it when application is closed. Using smart pointers here would give you exactly the same result. The programmer still needs to remember to delete/free the memory when necessary for "performance" reasons like that.

                              Let me ask you this question,please. How best do you write a parented project like this:

                              What you wrote seems fine. Whether you run some task for several hours or for 1 minute does not matter at all from memory perspective.

                              (Z(:^

                              tomyT 1 Reply Last reply
                              3
                              • sierdzioS sierdzio

                                @tomy said in Resource management in Qt:

                                I don't think Qt's parent-child mechanism is completely successful in that objective, because the resources are mainly freed when the project closes. While modern OSes do the same task after closing the program, making Qt's work actually useless in effect.

                                As stated before - that depends solely on how you build your UI. If you have a GUI app - let's say a web browser - then obviously the UI needs to stay in memory while the application is open. Otherwise users won't see anything... and these resources need to be freed only when the whole application is being closed. There is nothing that smart pointers would change in this scenario.

                                There are parts of that app, though, that do benefit from more smartness - browser tabs. Each new tab allocates memory, and closing the tab should free that memory. With Qt's approach (parent-child), you don't have any memory leaks here: a tab is created, added to the tree. You can delete it when the tab is closed, but if you forget to do it in code, no memory will leak - Qt will "remember" to free it when application is closed. Using smart pointers here would give you exactly the same result. The programmer still needs to remember to delete/free the memory when necessary for "performance" reasons like that.

                                Let me ask you this question,please. How best do you write a parented project like this:

                                What you wrote seems fine. Whether you run some task for several hours or for 1 minute does not matter at all from memory perspective.

                                tomyT Offline
                                tomyT Offline
                                tomy
                                wrote on last edited by
                                #15

                                @sierdzio

                                You can delete it when the tab is closed, but if you forget to do it in code, no memory will leak - Qt will "remember" to free it when application is closed

                                This is exactly the point I'm referring to. If the user continually opens (creates, dynamically) new tabs during work and closes them forgetting to set "delete" in code, without closing the main window of the browser, Qt releases those tabs' reserved memory beforehand, at the time of closing the app. Right, up to here?

                                I say it is useless, because most modern OSes do this task exactly when a program closes.

                                also you say:

                                Using smart pointers here would give you exactly the same result. The programmer still needs to remember to delete/free the memory when necessary

                                I disagree with this. Smart pointers have a "delete" in their destructors, so it's guaranteed that when they go out of scope, (just like the new tabs when they are closing), their resources using the destructors of those smart pointers are freed while the app is still running.

                                With what part of my opinions above do you disagree, please?

                                1 Reply Last reply
                                0
                                • tomyT tomy

                                  @Chris-Kawa

                                  You radically changed my code and now neither I get any new thing useful from that nor is the ambiguity of that relation more eliminated. I was reading your post of three years ago and was finding it useful.

                                  Just one point is clear to me for this post: smart pointers are created for occasions we "forget" to "delete" a memory block allocated dynamically. If we can write delete whenever needed, so why are modern pointers called "smart"?

                                  auto owner = std::make_unique<QPushButton>();

                                  This since isn't a static member doesn't work either on my Qt Creator!
                                  error: 'auto' not allowed in non-static class member

                                  kshegunovK Offline
                                  kshegunovK Offline
                                  kshegunov
                                  Moderators
                                  wrote on last edited by kshegunov
                                  #16

                                  @tomy said in Resource management in Qt:

                                  Just one point is clear to me for this post: smart pointers are created for occasions we "forget" to "delete" a memory block allocated dynamically. If we can write delete whenever needed, so why are modern pointers called "smart"?

                                  No they are not. They are created for specific circumstances where they're useful. The thing a scoped pointer is useful for is exception-safety. Shared data pointers (Qt) are created for COW (allowing shallow copies) and thus reentrancy. Shared pointers are for when the objects manage their own lifetimes - they're their own owner so to speak. If you don't allow exceptions then stack unwinding a scoped pointer gives you nothing. If your object is not managing its own lifetime then using a shared pointer means you're trying to fit a square peg in a round hole.

                                  This is exactly the point I'm referring to. If the user continually opens (creates, dynamically) new tabs during work and closes them forgetting to set "delete" in code, without closing the main window of the browser, Qt releases those tabs' reserved memory beforehand, at the time of closing the app. Right, up to here?

                                  If they're parented to something, then they're freed when the something is destroyed. It's not Qt's job (nor the OS's for that matter) to clean up your room, you know, is what we're saying. You need to tidy up, that's your responsibility as a programmer. Forgetting to delete what you acquired is a bug in your code, not in the library.

                                  I disagree with this. Smart pointers have a "delete" in their destructors, so it's guaranteed that when they go out of scope, (just like the new tabs when they are closing), their resources using the destructors of those smart pointers are freed while the app is still running.

                                  Same goes for the parent-child relationship. When the parent object goes out of scope (i.e. is deleted) then it's going to free its children, not before that, not at some unknown point in time.

                                  With what part of my opinions above do you disagree, please?

                                  I disagree with two things:

                                  1. You're not realizing a smart pointer is not a pointer but an object. The stack frees the object then the object is going to delete the data block.
                                  2. This is no different from what the parent does.

                                  Read and abide by the Qt Code of Conduct

                                  tomyT 1 Reply Last reply
                                  4
                                  • kshegunovK kshegunov

                                    @tomy said in Resource management in Qt:

                                    Just one point is clear to me for this post: smart pointers are created for occasions we "forget" to "delete" a memory block allocated dynamically. If we can write delete whenever needed, so why are modern pointers called "smart"?

                                    No they are not. They are created for specific circumstances where they're useful. The thing a scoped pointer is useful for is exception-safety. Shared data pointers (Qt) are created for COW (allowing shallow copies) and thus reentrancy. Shared pointers are for when the objects manage their own lifetimes - they're their own owner so to speak. If you don't allow exceptions then stack unwinding a scoped pointer gives you nothing. If your object is not managing its own lifetime then using a shared pointer means you're trying to fit a square peg in a round hole.

                                    This is exactly the point I'm referring to. If the user continually opens (creates, dynamically) new tabs during work and closes them forgetting to set "delete" in code, without closing the main window of the browser, Qt releases those tabs' reserved memory beforehand, at the time of closing the app. Right, up to here?

                                    If they're parented to something, then they're freed when the something is destroyed. It's not Qt's job (nor the OS's for that matter) to clean up your room, you know, is what we're saying. You need to tidy up, that's your responsibility as a programmer. Forgetting to delete what you acquired is a bug in your code, not in the library.

                                    I disagree with this. Smart pointers have a "delete" in their destructors, so it's guaranteed that when they go out of scope, (just like the new tabs when they are closing), their resources using the destructors of those smart pointers are freed while the app is still running.

                                    Same goes for the parent-child relationship. When the parent object goes out of scope (i.e. is deleted) then it's going to free its children, not before that, not at some unknown point in time.

                                    With what part of my opinions above do you disagree, please?

                                    I disagree with two things:

                                    1. You're not realizing a smart pointer is not a pointer but an object. The stack frees the object then the object is going to delete the data block.
                                    2. This is no different from what the parent does.
                                    tomyT Offline
                                    tomyT Offline
                                    tomy
                                    wrote on last edited by
                                    #17

                                    @kshegunov

                                    They are created for specific circumstances where they're useful.

                                    What circumstances, only exceptions?

                                    So you agree that, when each new tab in the browser example is created using a smart pointer, its resource will be freed when it closes, not necessarily at the time the user closes the whole app.

                                    You're not realizing a smart pointer is not a pointer but an object.

                                    I know that. Once again in the above example, when a new tab closes, that "object" goes out of scope handling the destructor of its class to run freeing the newly closed tab's resource.

                                    So if this scenario is done properly with smart pointers, and you say the same goes with the parent-child relationship if they're parented to something, OK. What is that thing, in our example? The main window of the browser?

                                    kshegunovK 1 Reply Last reply
                                    0
                                    • tomyT tomy

                                      @kshegunov

                                      They are created for specific circumstances where they're useful.

                                      What circumstances, only exceptions?

                                      So you agree that, when each new tab in the browser example is created using a smart pointer, its resource will be freed when it closes, not necessarily at the time the user closes the whole app.

                                      You're not realizing a smart pointer is not a pointer but an object.

                                      I know that. Once again in the above example, when a new tab closes, that "object" goes out of scope handling the destructor of its class to run freeing the newly closed tab's resource.

                                      So if this scenario is done properly with smart pointers, and you say the same goes with the parent-child relationship if they're parented to something, OK. What is that thing, in our example? The main window of the browser?

                                      kshegunovK Offline
                                      kshegunovK Offline
                                      kshegunov
                                      Moderators
                                      wrote on last edited by kshegunov
                                      #18

                                      @tomy said in Resource management in Qt:

                                      What circumstances, only exceptions?

                                      Only? That's enough not to leak memory all over the place.

                                      So you agree that, when each new tab in the browser example is created using a smart pointer, its resource will be freed when it closes, not necessarily at the time the user closes the whole app.

                                      No, I don't.

                                      Once again in the above example, when a new tab closes, that "object" goes out of scope handling the destructor of its class to run freeing the newly closed tab's resource.

                                      There's no such example that I could see.

                                      So if this scenario is done properly with smart pointers, and you say the same goes with the parent-child relationship

                                      It does.

                                      if they're parented to something, OK. What is that thing, in our example? The main window of the browser?

                                      Usually (actually almost always) you parent widgets to their visual parent. For a tab that could be a dialog or a main window. For a dialog it can be another dialog or a main window, etc. None of the smart pointers can know if you want to free the object when you close the tab or not, so that's up to you. You can for example want the tab to persist over some time, even if not visible. And I've done this, whenever I have a widget that's heavy to populate for w/e reason. On the other hand when the dialog's deleted its going to free all it's child widgets (provided they're parented), so I really don't see why you'd want to even use a smart pointer in that case. Moreover I'd rather create the widgets on the stack, where applicable, then the language is freeing them for me, no need to call new, nor delete.

                                      Read and abide by the Qt Code of Conduct

                                      tomyT 1 Reply Last reply
                                      3
                                      • kshegunovK kshegunov

                                        @tomy said in Resource management in Qt:

                                        What circumstances, only exceptions?

                                        Only? That's enough not to leak memory all over the place.

                                        So you agree that, when each new tab in the browser example is created using a smart pointer, its resource will be freed when it closes, not necessarily at the time the user closes the whole app.

                                        No, I don't.

                                        Once again in the above example, when a new tab closes, that "object" goes out of scope handling the destructor of its class to run freeing the newly closed tab's resource.

                                        There's no such example that I could see.

                                        So if this scenario is done properly with smart pointers, and you say the same goes with the parent-child relationship

                                        It does.

                                        if they're parented to something, OK. What is that thing, in our example? The main window of the browser?

                                        Usually (actually almost always) you parent widgets to their visual parent. For a tab that could be a dialog or a main window. For a dialog it can be another dialog or a main window, etc. None of the smart pointers can know if you want to free the object when you close the tab or not, so that's up to you. You can for example want the tab to persist over some time, even if not visible. And I've done this, whenever I have a widget that's heavy to populate for w/e reason. On the other hand when the dialog's deleted its going to free all it's child widgets (provided they're parented), so I really don't see why you'd want to even use a smart pointer in that case. Moreover I'd rather create the widgets on the stack, where applicable, then the language is freeing them for me, no need to call new, nor delete.

                                        tomyT Offline
                                        tomyT Offline
                                        tomy
                                        wrote on last edited by
                                        #19

                                        @kshegunov

                                        Thank you.
                                        The issue still is not solved for me, but I would rather not continue this thread because it's just this way being stretched out more and more.

                                        Probably, in the future, or when studying other resources, I can comprehend the matter.

                                        KroMignonK 1 Reply Last reply
                                        0
                                        • tomyT tomy

                                          @kshegunov

                                          Thank you.
                                          The issue still is not solved for me, but I would rather not continue this thread because it's just this way being stretched out more and more.

                                          Probably, in the future, or when studying other resources, I can comprehend the matter.

                                          KroMignonK Offline
                                          KroMignonK Offline
                                          KroMignon
                                          wrote on last edited by
                                          #20

                                          @tomy Just my 2 cts about parent relationship of QtObject. This has nothing to do with smartpointer philosophy, the point is to ensure than every child object will be distroyed when the parent object is distroyed.
                                          So combining smartpointers and parent-child relationship is a very bad idea, because smartpointer are there to clear memory when all copies of the pointer are distroyed... So you will have double memory release ==> crash!
                                          But Qt also includes another type of smartpointer called QPointer, which will becomes null when the QObject is deleted, and distroying the the QPointer, will not

                                          The other advantage of parent-child relationship, is that parent and childs always living in the same thread, moving parent object to another will also move all child to the same thread. Moving childs to another thread is not allowed.

                                          There is only 1 rule about parent-child relationship and smartpointer, avoid to combine them.

                                          It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                                          1 Reply Last reply
                                          2

                                          • Login

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