QT之内存泄漏管理
2016-12-13 21:06
337 查看
QT之内存泄漏管理
QT之内存泄漏管理插叙
QT半自动内存管理
内存例子
内存管理陷阱
QT智能指针
参考链接
结尾
插叙
在C++学习里,我们都知道,New和Delete是成对出现的,如果你忘记了Delete,少了还可以容忍,多了,你就重启应用吧,因为你占用内存太大了!在QT里,我们经常会看到很多NEW出来的对象,但是不需要我们自己去Delete掉。为什么会这样?那是因为QT里,有很多它已经帮我们处理掉了,但是你必须认识到,什么时候QT会帮我清理掉,什么时候却不会。
不是任何时候QT都会帮我们释放掉的,认为QT会帮自己释放掉,结果却造成内存泄漏!内存泄漏!内存泄漏!
QT半自动内存管理
在Qt中,以下情况下你new出的对象你可以不用亲自去delete (但你应该清楚delete在何处被Qt调用的,怎么被调用的):(1)QObject及其派生类的对象,如果其parent非0,那么其parent析构时会析构该对象。
(2)QWidget及其派生类的对象,可以设置 Qt::WA_DeleteOnClose 标志位(当close时会析构该对象)。
(3)QAbstractAnimation派生类的对象,可以设置 QAbstractAnimation::DeleteWhenStopped。
(4)QRunnable::setAutoDelete()、MediaSource::setAutoDelete()。
…
注意:这些用法会有些陷阱。
内存例子
(1)#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(); } //分析:(1)label 既没有指定parent,也没有对其调用delete,所以会造成内存泄漏。
(2)
#include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApplication a(argc, argv); QLabel label("Hello Qt!"); label.show(); return a.exec(); } //分配对象到栈上而不是堆上
(3)
#include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApplication a(argc, argv); QLabel *label = new QLabel("Hello Qt!"); label->setAttribute(Qt::WA_DeleteOnClose); label->show(); return a.exec(); } //设置标志位,close()后会delete label。
(4)
#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; } //new后手动delete
内存管理陷阱
(1)#include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel label("Hello Qt!"); label.show(); label.setAttribute(Qt::WA_DeleteOnClose); return app.exec(); } //程序崩溃,因为label被close时,delete &label;但label对象是在栈上分配的内存空间,delete栈上的地址会出错。
(2)
#include <QApplication> #include <QLabel> int main(int argc, char* argv[]) { QApplication app(argc, argv); QLabel label("Hello Qt!"); QWidget w; label.setParent(&w); w.show(); return app.exec(); } //Object内部有一个list,会保存children,还有一个指针保存parent,当自己析构时,会自己从parent列表中删除并且析构所有的children。w比label先被析构,当w被析构时,会删除chilren列表中的对象label,但label是分配到栈上的,因delete栈上的对象而出错。
(3)
#include <QApplication> #include <QLabel> int main(int argc, char* argv[]) { QApplication app(argc, argv); QWidget *w = new QWidget; QLabel *label = new QLabel("Hello Qt!"); label->setParent(w); w->show(); delete w; label->setText("go"); //野指针 return app.exec(); } //程序异常结束,delete w时会delete label,label成为野指针,调用label->setText(“Go”);出错。
QT智能指针
(1)QPointer
QPointer是一个模板类。它很类似一个普通的指针,不同之处在于,QPointer 可以监视动态分配空间的对象,并且在对象被 delete 的时候及时更新。
QPointer的现实原理:在QPointer保存了一个QObject的指针,并把这个指针的指针(双指针)交给全局变量管理,而QObject 在销毁时(析构函数,QWidget是通过自己的析构函数的,而不是依赖QObject的)会调用QObjectPrivate::clearGuards 函数来把全局 GuardHash 的那个双指针置为*零,因为是双指针的问题,所以QPointer中指针当然也为零了。用isNull 判断就为空了。
// QPointer 表现类似普通指针 QDate *mydate = new QDate(QDate::currentDate()); QPointer mypointer = mydata; mydate->year(); // -> 2005 mypointer->year(); // -> 2005 // 当对象 delete 之后,QPointer 会有不同的表现 delete mydate; if(mydate == NULL) printf("clean pointer"); else printf("dangling pointer"); // 输出 dangling pointer if(mypointer.isNull()) printf("clean pointer"); else printf("dangling pointer"); // 输出 clean pointer
(2)自动垃圾回收机制
QObjectCleanupHandler :
Qt 对象清理器是实现自动垃圾回收的很重要的一部分。QObjectCleanupHandler可以注册很多子对象,并在自己删除的时候自动删除所有子对象。同时,它也可以识别出是否有子对象被删 除,从而将其从它的子对象列表中删除。这个类可以用于不在同一层次中的类的清理操作,例如,当按钮按下时需要关闭很多窗口,由于窗口的 parent 属性不可能设置为别的窗口的 button,此时使用这个类就会相当方便。
#include <QApplication> #include <QObjectCleanupHandler> #include <QPushButton> int main(int argc, char* argv[]) { QApplication app(argc, argv); // 创建实例 QObjectCleanupHandler *cleaner = new QObjectCleanupHandler; // 创建窗口 QPushButton *w = new QPushButton("Remove Me"); w->show(); // 注册第一个按钮 cleaner->add(w); // 如果第一个按钮点击之后,删除自身 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); QObject::connect(w, SIGNAL(clicked()), cleaner, SLOT(deleteLater())); w->show(); return app.exec(); } //在上面的代码中,创建了三个仅有一个按钮的窗口。第一个按钮点击后,会删除掉自己(通过 deleteLater() 槽),此时,cleaner 会自动将其从自己的列表中清除。第三个按钮点击后会删除 cleaner,这样做会同时删除掉所有未关闭的窗口。
参考链接
http://blog.csdn.net/u013711616/article/details/52688581结尾
只为记录,只为分享! 愿所写能对你有所帮助。Good Good Study, Day Day Up!相关文章推荐
- Qt 内存管理机制
- [z]Qt 内存管理机制
- QT中对内存的管理
- 【QT】表格控件+qt中没delete是否会内存泄漏
- QT中对内存的管理
- 内存泄漏检测工具.和一些内存管理建议
- 根据Facebook内存的管理使用,浅谈在iOS上自动检测内存泄漏问题
- C++/Qt 内存管理机制
- Qt 内存管理机制
- Qt 内存管理机制(转)
- Qt 内存管理机制
- 根据Facebook内存的管理使用,浅谈在iOS上自动检测内存泄漏问题
- qt 的QNetworkAccessManager的使用和防止内存泄漏
- Qt 内存管理机制
- Qt的内存管理机制
- Qt 内存管理机制
- Qt 内存管理机制
- Qt 内存管理机制
- QT 内存管理机制
- Qt 内存管理机制