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. QList<QObject*> and Memory Leak Issue
QtWS25 Last Chance

QList<QObject*> and Memory Leak Issue

Scheduled Pinned Locked Moved Solved General and Desktop
memory leakqlistqobjectpointer
15 Posts 5 Posters 14.7k Views
  • 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.
  • M Offline
    M Offline
    micland
    wrote on 8 Jun 2016, 07:41 last edited by
    #4

    Oh I missed the thing that you clear the list after adding 1000 items, so don't call listItems.reserve(1000000) but listItems.reserve(1000).
    As @Wieland said 1.5s for 1000 items to delete is a lot. And the measured time you're printing out also contains the creation and initialization of the item instances. Are you sure that the deletion is taking the time and not the initialization? If so, can you post the implementation of the destructor of your DynamicObject item class? I guess that there's anything time consuming... (or try to add just QObject instances instead of DynamicObject - does it take the same time to delete them?)

    1 Reply Last reply
    1
    • V Offline
      V Offline
      VRonin
      wrote on 8 Jun 2016, 07:51 last edited by
      #5
      This post is deleted!
      1 Reply Last reply
      0
      • M micland
        8 Jun 2016, 07:03

        3 thoughts:

        • If you want to delete all your items, you have to call qDeleteAll() (or delete each item manually in a separate loop) - QList does not delete your items because it's not the owner of the items (concrete: the list hold just a bunch of pointers and does not own the memory where the pointers point to - another approch is to hold the items on the stack so the list will hold the items and not just the pointers, but that's not possible for QObject instances - they shall be held on the heap, see http://doc.qt.io/qt-5/qobject.html#no-copy-constructor-or-assignment-operator).

        • If you add so much items try to call listItems.reserve(1000000) at first to prevent frequently resizing of the internal structure.

        • If your DynamicObject class inherits QObject you can pass another QObject instance as parent to the constructor so your item will be automatically deleted when the parent object gets deleted (see http://doc.qt.io/qt-5/objecttrees.html). But QList does not inherit from QObject so it can't be used as parent.

        D Offline
        D Offline
        Dong
        wrote on 8 Jun 2016, 07:59 last edited by Dong 6 Aug 2016, 08:06
        #6

        @micland

        • 1st: I use DynamicObject with Dynamic Properties to contain Unknown Data Structure get from anonymous Service.
        • 2nd: I need to use a list of DynamicObject on QML, that why I have to use QList<QObject*>
          My related topic here

        @Wieland

        • I mean-sure all "create - add - delete - clear" process in above sample code. May be I will break it out.
        • If I change each Item instantiate with QObject* item = new QObject();
          It only take 0.4 - 0.5s (May be Data conversion between QObject & DynamicObject is take time.

        @VRonin
        - I'm already defined Destructor in DynamicObject (in fact: It doesn't have any predefined or instantiated properties so Destructor is not necessary )

        M 1 Reply Last reply 8 Jun 2016, 08:06
        0
        • D Dong
          8 Jun 2016, 07:59

          @micland

          • 1st: I use DynamicObject with Dynamic Properties to contain Unknown Data Structure get from anonymous Service.
          • 2nd: I need to use a list of DynamicObject on QML, that why I have to use QList<QObject*>
            My related topic here

          @Wieland

          • I mean-sure all "create - add - delete - clear" process in above sample code. May be I will break it out.
          • If I change each Item instantiate with QObject* item = new QObject();
            It only take 0.4 - 0.5s (May be Data conversion between QObject & DynamicObject is take time.

          @VRonin
          - I'm already defined Destructor in DynamicObject (in fact: It doesn't have any predefined or instantiated properties so Destructor is not necessary )

          M Offline
          M Offline
          micland
          wrote on 8 Jun 2016, 08:06 last edited by
          #7

          @Dong said:

          • I mean-sure all "create - add - delete - clear" process in above sample code. May be I will break it out.
          • If I change each Item instantiate with QObject* item = new QObject();
            It only take 0.4 - 0.5s (May be Data conversion between QObject & DynamicObject is take time.

          Well if the operation is faster when using QObject instances than the time consuming part happens in your own constructor or destructor implementation. Since your QList is holding only pointers and not the items directly there's no "data conversion" that takes time (or try to use QList<DynamicObject*> - but that should not influence the timing).

          1 Reply Last reply
          0
          • D Offline
            D Offline
            Dong
            wrote on 8 Jun 2016, 09:37 last edited by
            #8

            "It definitely slow on Instantiate DynamicObject."
            After investigate, I found that Signals/Slots/Functions in DynamicObject also affect the Instantiate process.

            • I am create 1000 items
              • Without any Signal/Slot/Function : it only take 200ms
              • With 5 Q_INVOKABLE functions, 1 Signal, 1 Slot : it take 950ms

            And my DynamicObject have about 10 Q_INVOKABLE functions, 2 Signals, 2 Slots

            Below is the causes For Memory Leak Issues (Please correct if I'm wrong)

            • Delete pointer when not using it.
            • Use Destructor to clear properties.
            • Use Parent - Child Tree to manage delete Child Objects automatically when Parent Object deleted.
            K M 2 Replies Last reply 8 Jun 2016, 12:29
            0
            • D Dong
              8 Jun 2016, 09:37

              "It definitely slow on Instantiate DynamicObject."
              After investigate, I found that Signals/Slots/Functions in DynamicObject also affect the Instantiate process.

              • I am create 1000 items
                • Without any Signal/Slot/Function : it only take 200ms
                • With 5 Q_INVOKABLE functions, 1 Signal, 1 Slot : it take 950ms

              And my DynamicObject have about 10 Q_INVOKABLE functions, 2 Signals, 2 Slots

              Below is the causes For Memory Leak Issues (Please correct if I'm wrong)

              • Delete pointer when not using it.
              • Use Destructor to clear properties.
              • Use Parent - Child Tree to manage delete Child Objects automatically when Parent Object deleted.
              K Offline
              K Offline
              kshegunov
              Moderators
              wrote on 8 Jun 2016, 12:29 last edited by
              #9

              @Dong

              After investigate, I found that Signals/Slots/Functions in DynamicObject also affect the Instantiate process.

              I am create 1000 items
              Without any Signal/Slot/Function : it only take 200ms
              With 5 Q_INVOKABLE functions, 1 Signal, 1 Slot : it take 950ms
              And my DynamicObject have about 10 Q_INVOKABLE functions, 2 Signals, 2 Slots

              This is very suspicious. 1k objects is nothing(!). Also I don't see how you'd get 5 fold increase by using 5 invokables. The macro expands to nothing and moc generates only a few bytes for it. So, as @micland already asked, how do you measure those times?

              Delete pointer when not using it.
              Use Parent - Child Tree to manage delete Child Objects automatically when Parent Object deleted.

              This will keep you free of memory leaks for the most part, yes.

              Use Destructor to clear properties.

              Never call the destructor directly unless you know what you're doing.

              Kind regards.

              Read and abide by the Qt Code of Conduct

              1 Reply Last reply
              1
              • D Dong
                8 Jun 2016, 09:37

                "It definitely slow on Instantiate DynamicObject."
                After investigate, I found that Signals/Slots/Functions in DynamicObject also affect the Instantiate process.

                • I am create 1000 items
                  • Without any Signal/Slot/Function : it only take 200ms
                  • With 5 Q_INVOKABLE functions, 1 Signal, 1 Slot : it take 950ms

                And my DynamicObject have about 10 Q_INVOKABLE functions, 2 Signals, 2 Slots

                Below is the causes For Memory Leak Issues (Please correct if I'm wrong)

                • Delete pointer when not using it.
                • Use Destructor to clear properties.
                • Use Parent - Child Tree to manage delete Child Objects automatically when Parent Object deleted.
                M Offline
                M Offline
                micland
                wrote on 8 Jun 2016, 13:45 last edited by
                #10

                @Dong said:

                • Use Destructor to clear properties.

                In addition to the notes of @kshegunov, what exactly do you mean with "clear properties"?
                The properties specified using setProperty(...) are owned and managed by QObject so there is no need to clear them. You only have to clean up in your destructor what you have acquired in your constructor (memory, resources, etc.) - but that's common C++, nothing Qt specific. Qt helps you to reduce the the required clean up, for example with the mentioned object tree (a parent instance owns and deletes its child instances with parent/child relation here in a linked way, not an inherited way).

                But using Qt does not require more action to avoid memory leaks than common C++ does (usually).

                1 Reply Last reply
                0
                • D Offline
                  D Offline
                  Dong
                  wrote on 9 Jun 2016, 01:18 last edited by
                  #11

                  Thanks you for all comment and suggestions.

                  • Because I need to "binding" between Qml's Properties & Dynamic Properties. So, I store a mapping in my object.
                    Do I need to clean up that map in Destructor?

                  Here is my logged time use qDebug():
                  Action: "Start time"
                  Create Items: "2016-06-08 16:15:45 553"
                  Delete Items: "2016-06-08 16:15:46 062"
                  Clear List: "2016-06-08 16:15:46 095"
                  Create Items: "2016-06-08 16:15:46 095"
                  Delete Items: "2016-06-08 16:15:46 692"
                  Clear List: "2016-06-08 16:15:46 737"
                  Create Items: "2016-06-08 16:15:46 738"
                  Delete Items: "2016-06-08 16:15:47 686"
                  Clear List: "2016-06-08 16:15:47 735"
                  Create Items: "2016-06-08 16:15:47 736"
                  Delete Items: "2016-06-08 16:15:48 693"
                  Clear List: "2016-06-08 16:15:48 733"
                  Create Items: "2016-06-08 16:15:48 741"
                  Delete Items: "2016-06-08 16:15:49 724"
                  Clear List: "2016-06-08 16:15:49 768"

                  K 1 Reply Last reply 9 Jun 2016, 12:20
                  0
                  • D Dong
                    9 Jun 2016, 01:18

                    Thanks you for all comment and suggestions.

                    • Because I need to "binding" between Qml's Properties & Dynamic Properties. So, I store a mapping in my object.
                      Do I need to clean up that map in Destructor?

                    Here is my logged time use qDebug():
                    Action: "Start time"
                    Create Items: "2016-06-08 16:15:45 553"
                    Delete Items: "2016-06-08 16:15:46 062"
                    Clear List: "2016-06-08 16:15:46 095"
                    Create Items: "2016-06-08 16:15:46 095"
                    Delete Items: "2016-06-08 16:15:46 692"
                    Clear List: "2016-06-08 16:15:46 737"
                    Create Items: "2016-06-08 16:15:46 738"
                    Delete Items: "2016-06-08 16:15:47 686"
                    Clear List: "2016-06-08 16:15:47 735"
                    Create Items: "2016-06-08 16:15:47 736"
                    Delete Items: "2016-06-08 16:15:48 693"
                    Clear List: "2016-06-08 16:15:48 733"
                    Create Items: "2016-06-08 16:15:48 741"
                    Delete Items: "2016-06-08 16:15:49 724"
                    Clear List: "2016-06-08 16:15:49 768"

                    K Offline
                    K Offline
                    kshegunov
                    Moderators
                    wrote on 9 Jun 2016, 12:20 last edited by
                    #12

                    @Dong

                    Here is my logged time use qDebug()

                    This information is useless. You can't benchmark code like that. You need to repeat the block a few times and you need an okay timer (QElapsedTimer for example, QDateTime::currentDateTime() will simply not cut it!). Also you need to make sure you have the same (or almost the same) conditions on every benchmark iteration.

                    Because I need to "binding" between Qml's Properties & Dynamic Properties. So, I store a mapping in my object.

                    Show us how you do that, please. QML's properties are already dynamic properties, so I can't help but wonder what mapping you need exactly.

                    Read and abide by the Qt Code of Conduct

                    D 1 Reply Last reply 10 Jun 2016, 02:43
                    0
                    • K kshegunov
                      9 Jun 2016, 12:20

                      @Dong

                      Here is my logged time use qDebug()

                      This information is useless. You can't benchmark code like that. You need to repeat the block a few times and you need an okay timer (QElapsedTimer for example, QDateTime::currentDateTime() will simply not cut it!). Also you need to make sure you have the same (or almost the same) conditions on every benchmark iteration.

                      Because I need to "binding" between Qml's Properties & Dynamic Properties. So, I store a mapping in my object.

                      Show us how you do that, please. QML's properties are already dynamic properties, so I can't help but wonder what mapping you need exactly.

                      D Offline
                      D Offline
                      Dong
                      wrote on 10 Jun 2016, 02:43 last edited by
                      #13

                      @kshegunov

                      About the benchmark thing, I use qDebug to print out the start time of each process.
                      Above log sample is process with 5000 items (5 times * 1000)
                      But Just forget about the benchmark thing ...

                      here is my other post about my situation.
                      Currently I only can auto binding one way from View Model (C++) to View (Qml)

                      Here is my DynamicObject definition

                      class DynamicObject : public QObject
                      {
                          Q_OBJECT
                      private:
                          QObject* getProperty(const QStringList &propPath) const;
                          void CopyObject(QObject * fromObj, QObject * toObj) const;
                      
                          // PROPERTIES
                          QMap<QString, QVariant> bindingList;                //Mapping between 1 bindingKey to 1 bindingInfo
                          QMap<QString, QStringList> cppToQml;                //Mapping between 1 cppProperty to multiple qmlProperties
                          QList<QString> bindedChildObjects;                  //List of child object had propertyChanged signal - slot connected
                      
                          void removeBindingByQmlProperty(QString objKey, QString propName);
                      public:
                      
                          FormMetaData formMetaData;
                          void ClearBinding();
                      
                          int getIndexFromPropertyName(QString &propName) const;
                          // CONSTRUCTORS
                          DynamicObject(QObject *parent = 0);
                          DynamicObject(AdsProvider::EnumAdsProvider engine, QString objType);
                      
                          // PROPERTIES
                          AdsProvider::EnumAdsProvider Engine;
                          QString ObjectType;
                      
                          // FUNCTIONS
                          Q_INVOKABLE void autoBinding(QObject* qmlObj, QString qmlProp, QObject* cppObj, QString cppProp);
                          Q_INVOKABLE QObject* thisContextObject();
                      
                          Q_INVOKABLE QVariant binding(const QString &propName);
                          //===== Normal value Set function =====
                          Q_INVOKABLE void setValue(const QString &propPath, const QVariant &value);
                      
                          //===== QList functions =====
                          ///Update a list item with new item (propPath must point to an item by index)
                          Q_INVOKABLE void updateListItem(const QString &propPath, DynamicObject *obj);
                          Q_INVOKABLE void insertListItem(const QString &propPath, DynamicObject *obj);
                          Q_INVOKABLE void removeListItem(const QString &propPath);
                          Q_INVOKABLE void clearListItem(const QString &propPath);
                          Q_INVOKABLE int indexOfItem(const QString &propPath, const QVariant &item, const QString &propToCompare);
                      
                          bool event(QEvent *event);
                          void CopyTo(QObject *toObj);
                      signals:
                          void propertyChanged(QObject* contextObject, QVariant propName);
                      public slots:
                          void onChildPropertyChanged(QObject* cppObj, QVariant propName);
                          void onQmlObjectDestroyed(QObject * obj = 0);
                      };
                      

                      About ModelData pointer, I'll construct it will ViewModel pointer as parent. it should be work.

                      May be I'll investigate more on this problems & post the result later.

                      Thanks you all !!!

                      K 1 Reply Last reply 10 Jun 2016, 17:59
                      0
                      • D Dong
                        10 Jun 2016, 02:43

                        @kshegunov

                        About the benchmark thing, I use qDebug to print out the start time of each process.
                        Above log sample is process with 5000 items (5 times * 1000)
                        But Just forget about the benchmark thing ...

                        here is my other post about my situation.
                        Currently I only can auto binding one way from View Model (C++) to View (Qml)

                        Here is my DynamicObject definition

                        class DynamicObject : public QObject
                        {
                            Q_OBJECT
                        private:
                            QObject* getProperty(const QStringList &propPath) const;
                            void CopyObject(QObject * fromObj, QObject * toObj) const;
                        
                            // PROPERTIES
                            QMap<QString, QVariant> bindingList;                //Mapping between 1 bindingKey to 1 bindingInfo
                            QMap<QString, QStringList> cppToQml;                //Mapping between 1 cppProperty to multiple qmlProperties
                            QList<QString> bindedChildObjects;                  //List of child object had propertyChanged signal - slot connected
                        
                            void removeBindingByQmlProperty(QString objKey, QString propName);
                        public:
                        
                            FormMetaData formMetaData;
                            void ClearBinding();
                        
                            int getIndexFromPropertyName(QString &propName) const;
                            // CONSTRUCTORS
                            DynamicObject(QObject *parent = 0);
                            DynamicObject(AdsProvider::EnumAdsProvider engine, QString objType);
                        
                            // PROPERTIES
                            AdsProvider::EnumAdsProvider Engine;
                            QString ObjectType;
                        
                            // FUNCTIONS
                            Q_INVOKABLE void autoBinding(QObject* qmlObj, QString qmlProp, QObject* cppObj, QString cppProp);
                            Q_INVOKABLE QObject* thisContextObject();
                        
                            Q_INVOKABLE QVariant binding(const QString &propName);
                            //===== Normal value Set function =====
                            Q_INVOKABLE void setValue(const QString &propPath, const QVariant &value);
                        
                            //===== QList functions =====
                            ///Update a list item with new item (propPath must point to an item by index)
                            Q_INVOKABLE void updateListItem(const QString &propPath, DynamicObject *obj);
                            Q_INVOKABLE void insertListItem(const QString &propPath, DynamicObject *obj);
                            Q_INVOKABLE void removeListItem(const QString &propPath);
                            Q_INVOKABLE void clearListItem(const QString &propPath);
                            Q_INVOKABLE int indexOfItem(const QString &propPath, const QVariant &item, const QString &propToCompare);
                        
                            bool event(QEvent *event);
                            void CopyTo(QObject *toObj);
                        signals:
                            void propertyChanged(QObject* contextObject, QVariant propName);
                        public slots:
                            void onChildPropertyChanged(QObject* cppObj, QVariant propName);
                            void onQmlObjectDestroyed(QObject * obj = 0);
                        };
                        

                        About ModelData pointer, I'll construct it will ViewModel pointer as parent. it should be work.

                        May be I'll investigate more on this problems & post the result later.

                        Thanks you all !!!

                        K Offline
                        K Offline
                        kshegunov
                        Moderators
                        wrote on 10 Jun 2016, 17:59 last edited by
                        #14

                        @Dong

                        About the benchmark thing, I use qDebug to print out the start time of each process.

                        Yes indeed. I meant that you should average a few runs to get a reasonable estimation for how much time it takes. And also QDateTime is not really meant to give you real precise timing, it's intended for dates and time (ordinary clock time).

                        Currently I only can auto binding one way from View Model (C++) to View (Qml)

                        To be absolutely candid my knowledge of QML is really rudimentary, but isn't it this how it was intended in the first place?

                        Kind regards.

                        Read and abide by the Qt Code of Conduct

                        D 1 Reply Last reply 13 Jun 2016, 05:55
                        0
                        • K kshegunov
                          10 Jun 2016, 17:59

                          @Dong

                          About the benchmark thing, I use qDebug to print out the start time of each process.

                          Yes indeed. I meant that you should average a few runs to get a reasonable estimation for how much time it takes. And also QDateTime is not really meant to give you real precise timing, it's intended for dates and time (ordinary clock time).

                          Currently I only can auto binding one way from View Model (C++) to View (Qml)

                          To be absolutely candid my knowledge of QML is really rudimentary, but isn't it this how it was intended in the first place?

                          Kind regards.

                          D Offline
                          D Offline
                          Dong
                          wrote on 13 Jun 2016, 05:55 last edited by
                          #15

                          @kshegunov
                          There is a reason why I can't use QT Property Binding (It only support predefined Property using Q_PROPERTY script).
                          Please take a look at my topic about Auto Binding 2 ways with Dynamic Property
                          But Binding is an other topic.

                          About "Object's pointers & Memory"
                          I also take an advise from a Pro in C++ & memory management.
                          His solution is implement a Factory Pattern to Create/Delete Object's pointers
                          (also free memory when an instance had no pointer to it.)
                          (I think I'll give it a try)

                          1 Reply Last reply
                          0

                          13/15

                          10 Jun 2016, 02:43

                          • Login

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