Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Memory Leak or Not?



  • Hello guys.
    This is my first post here.
    I came across with simple but important issue on dealing with QObject.
    The problem is:
    I have a simple ContactList class which inherits QObject.
    Here is ContactList.h:

    #ifndef CONTACTLIST_H
    #define CONTACTLIST_H
    
    #include <QObject>
    
    class ContactList : public QObject
    {
        Q_OBJECT
    public:
        explicit ContactList(QObject *parent = nullptr);
        ContactList(const QString& input_name, const QString& input_cellphone, QObject *parent = nullptr);
        ~ContactList();
        inline const QString& getName() const { return name; }
        inline const QString& getCellphone() const { return cellphone; }
    
    signals:
    
    public slots:
    
    private:
        QString name;
        QString cellphone;
    };
    
    #endif // CONTACTLIST_H
    

    ContactList.cpp:

    #include "contactlist.h"
    #include <iostream>
    using namespace std;
    
    ContactList::ContactList(QObject *parent) : QObject(parent)
    {
        cout << "Default ContactList Constructor Called!" << endl;
    }
    
    ContactList::ContactList(const QString &input_name, const QString &input_cellphone, QObject *parent) :
        QObject(parent),
        name(input_name),
        cellphone(input_cellphone)
    {
        cout << "ConstactList Constructor Called!" << endl;
    }
    
    ContactList::~ContactList()
    {
        cout << "ContactList Destructor Called!" << endl;
    }
    

    And finally main.cpp:

    #include <iostream>
    #include <QCoreApplication>
    #include "contactlist.h"
    
    using namespace std;
    
    int main(int argc, char *argv[])
    {
    
        {
            QObject* first_data = new ContactList("Jack", "++448294241");
        }
    
        cout << "Seems there is memory leak at above!" << endl;
    
        {
            QObject parent;
            QObject* second_data = new ContactList("Jack", "++448294241", &parent);
        }
    
        cout << "Seems there is no memory leak at above!" << endl;
    
        return 0;
    }
    

    After executing above code I got this:
    ConstactList Constructor Called!
    Seems there is memory leak at above!
    ConstactList Constructor Called!
    ContactList Destructor Called!
    Seems there is no memory leak at above!

    1- Is there any memory leak in this code specially when first_data is created?
    2- If there is no memory leak why I got a less destructor call?
    3- How does QObject detect that currently pointing to a stack or heap allocated object? (this step is very important because of different deletion process on stack or heap)
    Thanks in advance.


  • Lifetime Qt Champion

    @Nima-Ghorab said in Memory Leak or Not?:

    1- Is there any memory leak in this code specially when first_data is created?

    Yeah, there is a leak for first_data. You create a variable with new but don't delete it.

    3- How does QObject detect that currently pointing to a stack or heap allocated object? (this step is very important because of different deletion process on stack or heap)

    It does not. There is no magic behind. A stack variable is destroyed when it goes out of scope, i.e. at the first closing curly bracket '}' . Therefore the destructor for parent is called, and as second_data is parented to parent, it is destructed as well.

    Regards



  • Thank you so much.
    Dear aha_1980, I still get confuse about my third question.
    About my third question, please consider following code:

    #include <iostream>
    #include <QCoreApplication>
    #include "contactlist.h"
    
    using namespace std;
    
    int main(int argc, char *argv[])
    {
    
        {
            QObject first_parent;
            QObject* second_data = new ContactList("Jack", "++448294241", &first_parent);
        }
    
        {
            QObject second_parent;
            ContactList my_friend("John", "++38475887690", &second_parent);
            QObject* third_data = &my_friend;
        }
    
        cout << "Seems there is no memory leak at above!" << endl;
    
        return 0;
    }
    

    Based on what you said I still can't figure it out how first_parent can detect that its child is a heap allocated object and therefore delete it but in second_parent it can detect that its child is a stack allocated object and therefore does not delete it!
    Can you explain a little bit more how QObject works?
    Thank you so much.


  • Lifetime Qt Champion

    @Nima-Ghorab

    I don't have the complete details about the internal function, but reading ~QObject doc, you must not parent objects that are created on the stack, otherwise your program will crash.

    This implies, that if you give a parent, the object should be on the heap (created with new).

    Regards


  • Qt Champions 2019

    @aha_1980 said in Memory Leak or Not?:

    you should

    read: you must not except you unparent it before condestruction :)


  • Lifetime Qt Champion



  • Thank you so much @aha_1980.


Log in to reply