转载,原文链接:https://blog.csdn.net/libaineu2004/article/details/106771500

如果时间急迫,不想看完整文章,可以直接去到文章末尾,看结论。有我个人写的C++单例类,用于内存自动释放。

1、QtCreator编写C++代码,怎么检测内存泄漏?

请参见本人的另一篇博文:https://blog.csdn.net/libaineu2004/article/details/104071627

2、Qt中控件new之后需不需要delete的问题

https://blog.csdn.net/Aidam_Bo/article/details/86303096

  • QT的父子对象机制是在 QWidget和QOject中实现的。当我们使用父对象来创建一个对象的时候 ,父对象会把这个对象添加到自己的子对象列表中。当这个父对象被删除的时候,它会遍历它的子对象类表并且删除每一个子对象,然后子对象们自己再删除它们自己的子对象,这样递归调用直到所有对象都被删除。
  • 这种父子对象机制会在很大程度上简化我们的内存管理工作,减少内存泄露的风险。
  • 我们需要显式删除(就是用Delete删除)的对象是那些使用new创建的并且没有父对象的对象(切记是new的才要delete,
  • 通过成员函数获得的对象,没有特殊说明的,千万不要随便delete。
  • 如果我们在删除一个对象的父对象之前删除它,QT会自动地从它的父对象的子对象列表中移除它的。
  • Qt自动回收不像Java这种,有垃圾回收机制。
  • Qt自动回收是靠父子关系。父亲销毁了。他的孩子也销毁。
  • 所以为什么main函数里面main widget/dialog/mainWindow是分配在栈上的原因。
  • 其他new出来的东西都以这个widget作为父亲。 当程序最后结束了,main widget弹栈。
  • 父类被销毁。子类跟着被销毁。 所以你自己new出来的控件,如果没有父类,自己又不删除,那就会造成内存泄漏。

小结–Qt的半自动化的内存管理:

(1)QObject及其派生类的对象,如果其parent非0,那么其parent析构时会析构该对象。

(2)QWidget及其派生类的对象,可以设置 Qt::WA_DeleteOnClose 标志位(当close时会析构该对象)。

(3)QAbstractAnimation派生类的对象,可以设置 QAbstractAnimation::DeleteWhenStopped。

(4)QRunnable::setAutoDelete()、MediaSource::setAutoDelete()。

(5)父子关系:父对象、子对象、父子关系。这是Qt中所特有的,与类的继承关系无关,传递参数是与parent有关(基类、派生类,或父类、子类,这是对于派生体系来说的,与parent无关)。

3、Qt智能指针和QObject对象树系统(父子系统)结合使用出现的问题

https://blog.csdn.net/gamesdev/article/details/8724090

  • 首先要弄明白为什么qt只new不delete,父子对象管理模式先弄清楚,另外QScopedPoint有个接口data,返回正在管理的原始指针。
  • QObject自有对象树系统(父子系统),它在和其它QObject子类进行交互的时候会将对方的指针保存起来,形成父子关系,
  • 最终一个QObject子类指针会形成一个强大的树状结构,当父亲销毁的时候,会先销毁它的孩子(如果它的孩子是通过new操作符在堆上创建的话)。但是智能指针在保有QObject子类的时候会自动调用它的析构函数,从而引起事实上的两次delete,这个时候编译器的就会报错。
  • 那我熟悉的QScopedPointer来说,本来将它用在类的成员中是一个很好的选择,但是由于它保有的是QObject的子类,这个智能指针在和其它QObject子类交互的时候难免会被对方保有原始指针的值,在进入类的析构函数,QScopedPointer保有原始指针的值会被先于释放并置为“已删除”的值0xfeeefeee,这个时候再通过智能指针的自动清理只可能会带来运行错误。在qscopedpointer.h源码中,我们看到QScopedPointerDeleter类的cleanup静态函数并不带有在delete之前的指针的值检测,于是在delete一个无效的指针时,错误发生了。

4、为什么官方的Qt示例和教程不使用智能指针?

目前得出了一个结论:只要加入了QObject对象树系统(父子机制),那么内存管理不是你的事儿了,你也不应该管,也不应该让智能指针管。

  • 智能指针类std::unique_ptr和std::shared_ptr是内存管理。拥有这样一个智能指针意味着,你拥有指针。
  • 但是,在QObject使用QObject父级创建或派生类型时,所有权(清理责任)将交给父级QObject。
  • 在这种情况下,标准库智能指针是不必要的,甚至是危险的,因为它们可能会导致双重删除。
  • 然而,当一个QObject在堆上创建而没有父类时,QObject情况就非常不同。在这种情况下,你不应该只保存一个原始指针,
  • 而是一个智能指针,最好是一个std::unique_ptr对象。这样你就可以获得资源安全。
  • 如果你稍后将对象所有权交给QObject你可以使用的父项std::unique_ptr::release(),如下所示:
  auto obj = std::make_unique<MyObject>();// ... do some stuff that might throw ...QObject parentObject;obj->setParent( &parentObject );obj.release();

5、qDeleteAll与clear

https://blog.csdn.net/yao5hed/article/details/81092139

typedef struct _Defs
{int a;double d;QString s;
} Def;QList<Def*> defs;
for(int i=0;i<500000;i++)
{Def* dd = new Def;dd->a = 12;dd->d = 4.23;dd->s = "jda";defs.append(dd);
}qDebug()<<"before qDeleteAll: "<<defs.size();
qDeleteAll(defs);
qDebug()<<"after qDeleteAll: "<<defs.size();
defs.clear();

运行结果发现,不调用qDeleteAll的情况下,程序占内存78M;加上之后,只占内存12M。但是前后的size没有变化。

当T的类型为指针时,调用clear方法能置空,但并不能释放其内存。qDeleteAll可以释放容器元素内存,但没有对容器的置空操作,也就是size没变。所以qDeleteAll之后必须加上clear方法。

6、deleteLater

https://blog.csdn.net/yao5hed/article/details/81092168

void QObject::deleteLater()
{QCoreApplication::postEvent(this, new QDeferredDeleteEvent());
}bool QObject::event(QEvent *e)
{switch (e->type()) {......case QEvent::DeferredDelete:qDeleteInEventHandler(this);break;}
}void qDeleteInEventHandler(QObject *o)
{delete o;
}

Qt中不建议手动delete掉QObject对象。原因一:不注意父子关系会导致某个对象析构两次,一次是手动析构,还有一次是parent析构,后者可能会出现delete堆上的对象。delete是C++和QT共有的一个操作符即时使用实时就析构删除了,而Qt里的deletelater的原理是:QObject::deleteLater()并没有将对象立即销毁,而是向主消息循环发送了一个event,下一次主消息循环收到这个event之后才会销毁对象。 这样做的好处是可以在这些延迟删除的时间内完成一些操作,坏处就是内存释放会不及时。

应用例子:父窗体的子窗体在focusoutevent时deletelater();然后在主窗体绑定信号子窗体的destroy()信号和父窗体的槽函数,然后在槽函数中象父窗体调用父窗体的接口函数向父窗体发送子窗体的文本text();

7、QObjectCleanupHandler

https://blog.csdn.net/yao5hed/article/details/81092178

https://blog.csdn.net/luoyayun361/article/details/97250027

#include <QObjectCleanupHandler>
m_pCleanupHandler = new QObjectCleanupHandler();
m_pObj1 = new CObject();
m_pObj2 = new CObject();
m_pObj3 = new CObject();
m_pCleanupHandler->add(m_pObj1);
m_pCleanupHandler->add(m_pObj2);
m_pCleanupHandler->add(m_pObj3);
...
//最后只需要调用
m_pCleanupHandler->clear();

所有的对象都会全部释放。并且,如果其中有些对象已经在别的地方进行释放, 那就会自动从QObjectCleanupHandler管理列表中自动删除,不会重复删除。所以,即便是重复调用clear()也不会出问题。使用QObjectCleanupHandler进行资源管理非常方便。

x1、结论

1、QObject及其派生类的对象,如果其parent非0,那么其parent析构时会析构该对象。我们不必手动删除内存。

2、程序员自己new出来的QObject及其派生类的对象,如果没有父类,自己又不删除,那就会造成内存泄漏。怎么办?我们可以使用QObjectCleanupHandler的机制来管理内存,在应用程序结束之前释放它们。

附上我写的单例类:

autocleanuphandler.h

#ifndef CAUTOLEANUPHANDLER_H
#define CAUTOLEANUPHANDLER_H#include <QGlobalStatic>
#include <QObjectCleanupHandler>#define AUTOCLEANUPHANDLER CAutoCleanupHandler::instance()class CAutoCleanupHandler
{
public:CAutoCleanupHandler() {}virtual ~CAutoCleanupHandler() {}public:static CAutoCleanupHandler *instance();public:QObject *add(QObject *object);void remove(QObject *object);bool isEmpty() const;void clear();private:QObjectCleanupHandler m_cleanupHandler;
};#endif // CAUTOLEANUPHANDLER_H

autocleanuphandler.cpp

#include "autocleanuphandler.h"Q_GLOBAL_STATIC(CAutoCleanupHandler, clean)CAutoCleanupHandler *CAutoCleanupHandler::instance()
{return clean();
}QObject *CAutoCleanupHandler::add(QObject *object)
{return m_cleanupHandler.add(object);
}void CAutoCleanupHandler::remove(QObject *object)
{m_cleanupHandler.remove(object);
}bool CAutoCleanupHandler::isEmpty() const
{return m_cleanupHandler.isEmpty();
}void CAutoCleanupHandler::clear()
{m_cleanupHandler.clear();
}

使用举例:

//新建控件,无父类FormOptionsWorkpiece *workpiece = new FormOptionsWorkpiece();FormOptionsMotionctrlcard *motionctrlcard = new FormOptionsMotionctrlcard();FormOptionsMachinetool *machinetool = new FormOptionsMachinetool();FormOptionsCameraInstall *camerainstall = new FormOptionsCameraInstall();//添加内存对象AUTOCLEANUPHANDLER->add(workpiece);AUTOCLEANUPHANDLER->add(motionctrlcard);AUTOCLEANUPHANDLER->add(machinetool);AUTOCLEANUPHANDLER->add(camerainstall);//exe退出前,自动清理内存AUTOCLEANUPHANDLER->clear();

x2、参考文献

Qt浅谈之一:内存泄露(总结)

https://blog.csdn.net/taiyang1987912/article/details/29271549
https://www.cnblogs.com/lsgxeva/p/7811288.html

Qt父子对象内存管理实现简析

https://www.dushibaiyu.com/2014/07/qt-fuzi-neicun.html

Qt智能指针官方文档

https://doc.qt.io/qt-5/qsharedpointer.html
https://doc.qt.io/qt-5/qscopedpointer.html
https://doc.qt.io/qt-5/qobjectcleanuphandler.html

总结一下Qt内存泄漏检测与处理策略相关推荐

  1. qt内存泄漏检测_qt 关于内存泄漏的检测

    Qt 关于内存泄露的检测: 工具篇关于Qt 内存泄露的检测工具有很多种,一下挑几种来说: 1.检测已分配资源, 第一个工具是一个内存资源使用的监听器.它只能在模拟器上进行调试.可以使用快捷键来调用 按 ...

  2. QT - 内存泄漏检测

    一.安装vld-2.5.1-setup.exe 下载地址:https://archive.codeplex.com/?p=vld 二.pro中添加头文件目录与库目录 INCLUDEPATH += &q ...

  3. C++笔记-构造内存泄漏检测类的基本思路

    目录 基本概念 代码与实例 基本概念 这里主要的思路是,在一个对象在堆区创建后,就把他记录下来,也就是把他记录到某个地方,这个地方负责管理他(和Qt里面的对象树有异曲同工之妙)下面这个例子,把创建的新 ...

  4. 内存泄漏检测工具:Deleaker 2022

    用于 C++.C#..NET 和 DELPHI 的分析器 与 Visual Studio 完全集成 • 发现任何泄漏:内存.GDI.句柄和其他 • 配置非托管和 .NET 代码 • 支持 32 位和 ...

  5. Unix下C程序内存泄漏检测工具Valgrind安装与使用

    Valgrind是一款用于内存调试.内存泄漏检测以及性能分析的软件开发工具. Valgrind的最初作者是Julian Seward,他于2006年由于在开发Valgrind上的工作获得了第二届Goo ...

  6. OpenCV中的内存泄漏检测

    转自:http://chaishushan.blog.163.com/blog/static/130192897200911685559809/ 内存泄漏时程序开发中经常遇到的问题. 而且出现内存泄漏 ...

  7. JVM内存泄漏检测与处理

    JVM内存泄漏检测与处理(JVM Memory Leak detection and handling) JVM垃圾回收机制的原则和方法 JVM垃圾回收中一个基本原则是对象没有被引用或则引用其它对象, ...

  8. android内存泄漏原因分析,Android Studio3.6的内存泄漏检测功能 VS LeakCanary

    2020年2月,谷歌发布了Android Studio 3.6版.它包括一个新的"内存泄漏检测"功能.这是否意味着我们不再需要流行的内存泄漏检测库"Leak Canary ...

  9. 基于Android Studio的内存泄漏检测与解决全攻略

    自从Google在2013年发布了Android Studio后,Android Studio凭借着自己良好的内存优化,酷炫的UI主题,强大的自动补全提示以及Gradle的编译支持正逐步取代Eclip ...

最新文章

  1. 强化学习(八)价值函数的近似表示与Deep Q-Learning
  2. 注意了,Fastjson 最新高危漏洞来袭!
  3. 使用Dockerfile定制镜像来部署Tomcat项目
  4. DCMTK:类DVPSIPCClient的示例消息服务器
  5. ubuntu16.04编译安装boost
  6. mysql show status 过滤_给MySQL的show table status结果做过滤
  7. 电脑主板资料库 03【转至www.ongood.com.tw】【FreeXploiT收集整理】
  8. unix环境高级编程读后感
  9. win7 管理iphone日历_iPhone和Windows同步文件,这7个技巧让你的效率成倍增加
  10. JAVA-----集合子接口Queue及其子接口Deque
  11. Mysql数据库用户密码暴力破解
  12. 学计算机ps是什么,学PS电脑绘画要掌握什么呢?
  13. 响应式Web设计:HTML5和CSS3实战 读书笔记
  14. python爬取武汉二手房房价
  15. 使用java连接neo4j aura数据库
  16. 结合案例轻松理解PID到底是个啥?
  17. Python编程-爬虫原理与简单实践
  18. 河南对口计算机本科学校有哪些,河南计算机对口升学有哪些学校
  19. 【Oracle】CBO优化详解
  20. 成为数据分析师,需要具备哪些技能?

热门文章

  1. Qt Linguist翻译 介绍
  2. 全球首颗量子卫星炼成记:“墨子号”打造保密通信新产业
  3. 【I2C时序分析】-hym8563为列
  4. 来点色看看~SecureCRT-8.5配色方案设置
  5. mysql数据库添加某个IP访问
  6. JavaScript滚轮事件
  7. 乐鑫科技2021提前批软件类笔试题
  8. 解决win10系统 3dMax只能渲染一次的问题
  9. 不要仅为85%的用户设计:关注无障碍设计
  10. win10 UWP 剪贴板 Clipboard