QT Development (19)--qt memory leak problem
I. parent-child relationship between QT objects
QT The most basic and core classes are:Qobject,qobject has a list inside it, it saves children, and a pointer holds the parent, and when it's self-destructor, Will remove itself from the parent list and deconstruct all children.
There can be parent-child relationships between Qt objects, and each object can hold pointers to all its child objects, each with a pointer to its parent object.
when you specify Qt object, the parent object adds a pointer to the object in the list of child objects that holds a pointer to its parent object.
when When the Qt object is destroyed, it removes itself from the parent object's list of child objects and destroys all objects in the linked list of its own child objects.
When the Qt object is destroyed, the parent-child relationship is lifted and all child objects are destroyed.
Second,QT semi-automatic memory management
1. The object of the Qobject and its derived class, if its parent is not 0, the object is refactored when its parent is destructor. If both the parent and child objects are allocated on the stack, and the parent object's memory space is released first, the child object's space is freed when the parent object is freed, and a memory error occurs when the child object space is freed.
2. Qwidget and its derived class, you can set the QT::WA_DELETEONCLOSE flag bit (the object will be refactored when close).
3. qabstractanimation The object of the derived class, you can set Qabstractanimation::D eletewhenstopped.
4. qrunnable::setautodelete (), Mediasource::setautodelete ().
5. Parent-child relationships: Parents, child objects, parent-child relationships. This is unique in Qt, regardless of the inheritance of the class, which is related to the parent (base class, derived class, or parent class, subclass, which is not related to the derived system, parent).
iii. Examples ofQT memory leaks
1. Example one
#include <QApplication>
#include <QLabel>
int main (int argc, char *argv[])
{
Qapplication A (argc, argv);
Qlabel *label = new Qlabel ("Hello qt!");
Label->show ();
return A.exec ();
}
The label does not specify the parent and does not call delete on it, causing a memory leak.
Solution:
A, allocating objects on the stack instead of on the heap
#include <QApplication>
#include <QLabel>
int main (int argc, char *argv[])
{
Qapplication A (argc, argv);
Qlabel label ("Hello qt!");
Label.show ();
return A.exec ();
}
B, when you set the flag bit,close () deletes the label.
#include <QApplication>
#include <QLabel>
int main (int argc, char *argv[])
{
Qapplication A (argc, argv);
Qlabel *label = new Qlabel ("Hello qt!");
Label->show ();
Label->setattribute (Qt::wa_deleteonclose);
return A.exec ();
}
C, on the heap new allocation space, delete manual release
#include <QApplication>
#include <QLabel>
int main (int argc, char *argv[])
{
int ret = 0;
Qapplication A (argc, argv);
Qlabel *label = new Qlabel ("Hello qt!");
Label->show ();
ret = A.exec ();
Delete label;
return ret;
}
2.
Example Two
#include <QApplication>
#include <QLabel>
int main (int argc, char *argv[])
{
Qapplication A (argc, argv);
Qlabel label ("Hello qt!");
Label.show ();
Label.setattribute (Qt::wa_deleteonclose);
return A.exec ();
}
The Label object is the memory space allocated on the stack, and the address on the delete stack will be faulted.
3.
example Three
#include <QApplication>
#include <QLabel>
int main (int argc, char *argv[])
{
Qapplication A (argc, argv);
Qlabel label ("Hello qt!");
Qwidget W;
Label.setparent (&W);
W.show ();
return A.exec ();
}
W is destroyed first, and when W is refactored, the object label in the Chilren list is deleted, but the label is assigned to the stack, and an error occurs because of the object on the delete stack.
Solution:
A, Adjusts the position of the parent object to ensure that the child object has been refactored when the parent object is refactored
#include <QApplication>
#include <QLabel>
int main (int argc, char *argv[])
{
Qapplication A (argc, argv);
Qwidget W;
Qlabel label ("Hello qt!");
Label.setparent (&W);
W.show ();
return A.exec ();
}
B. Assigning child objects to heap space
#include <QApplication>
#include <QLabel>
int main (int argc, char *argv[])
{
Qapplication A (argc, argv);
Qlabel *label = new Qlabel ("Hello qt!");
Qwidget W;
Label->setparent (&W);
W.show ();
return A.exec ();
}
4.
example Four
when a Qobject is receiving the event queue is destroyed Midway , there will be an exception , so qt do not directly delete a qobject, if must do, To use Qobject's Deletelater () function, the Deletelater () function clears the memory after all events have been processed, and there is no problem even if the deletelater is called multiple times.
Four,
Smart Pointers1.
Qpointer
Qpointer is a template class that Qpointer can monitor dynamically allocated space objects and update them when the object is deleted.
Qpointer: In Qpointer, a qobject pointer is saved and the pointer (double pointer) is given to the global variable management, while the Qobject is destroyed (the destructor, Qwidget, is through its own destructor, Instead of relying on Qobject) will call the Qobjectprivate::clearguards function to set the global Guardhash of the double pointer to zero, because it is a double pointer problem, so qpointer pointer is of course zero. It is empty to judge with IsNull.
2.
std::auto_ptr
When Auto_ptr is destroyed, it automatically deletes the object it points to.
Five, garbage collection mechanism
1.
Qobjectcleanuphandler
the Qt object Cleaner is an important part of implementing automatic garbage collection. Qobjectcleanuphandler can register many sub-objects and automatically delete all child objects when they are deleted. At the same time, it can also identify if a child object has been deleted, thereby removing it from its list of child objects. The Qobjectcleanuphandler class can be used for cleanup of classes that are not in the same hierarchy, for example, when a button is pressed to close many windows, because the Parent property of the window cannot be set to a button on another window, It is convenient to use the Qobjectcleanuphandler class at this time .
#include <QApplication>
#include <QObjectCleanupHandler>
#include <QPushButton>
int main (int argc, char *argv[])
{
Qapplication A (argc, argv);
Qobjectcleanuphandler *cleaner = new Qobjectcleanuphandler;
Qpushbutton *w = new Qpushbutton ("Remove Me");
W->show ();
Cleaner->add (w);
Click the "Remove Me" button to delete itself
Qobject::connect (W, SIGNAL (clicked ()), W, SLOT (Deletelater ()));
w = new Qpushbutton ("nothing");
Cleaner->add (w);
W->show ();
w = new Qpushbutton ("Remove all");
Cleaner->add (w);
W->show ();
Click the "Remove all" button to remove all qobject
Qobject::connect (W, SIGNAL (clicked ()), cleaner, SLOT (Deletelater ()));
return A.exec ();
}
clicking the "remove me" button will remove itself (through the Deletelater () slot) and cleaner will automatically clear it from its own list. Clicking the "removeall" button deletes The cleaner, deleting all windows that are not closed and registering Qobject object of cleaner .
This article from "Life is endless, struggle not only" blog, declined reprint!
QT Development (19)--QT Memory leak issues