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

                        14/15

                        10 Jun 2016, 17:59

                        • Login

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