千家信息网

如何解决QT内存泄漏的问题

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,如何解决QT内存泄漏的问题,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。01前言前几天,项目开展了一次代码初次评审。会上,领导指出一些可
千家信息网最后更新 2026年11月02日如何解决QT内存泄漏的问题

如何解决QT内存泄漏的问题,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

    01前言

    前几天,项目开展了一次代码初次评审。会上,领导指出一些可能会带来内存泄漏的代码,如下图所示:

    图中的pLayout在new的时候没有指定任何父对象,且MainWindow的析构函数中也没有对pLayout做delete操作,这意味着为pLayout申请的内存空间在程序运行期间是一直没有得到释放的。实际上,项目代码中,还有许多这种"隐患":一个单例类的成员变量在new的时候没有指定父对象、一个静态类的成员在new的时候没有指定父对象……

    这些"隐患"为何在目前程序运行时没有暴露出问题?基于这个疑惑,我研究了QT的半自动化的内存管理,并结合实验进行结果验证,现将分析过程记录下来

    02 QT半自动化内存管理要点

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

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

    • QAbstractAnimation派生类的对象,可以设置 QAbstractAnimation::DeleteWhenStopped

    • QRunnable::setAutoDelete()、MediaSource::setAutoDelete()

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

    03实验过程详解

    堆空间的内存泄漏与改进方法实践实例

    继承QWidget类的Test类,通过new为其分配内存,没有设置WA_DeleteOnclose属性且使用完后也没有delete

    实验结果:关闭testWidget窗口后,没有调用其析构函数打印"test delete"信息。直到程序结束之前testWidget的申请的内存空间都未被释放

    改进方法A

    为testWidget窗口设置Qt::WA_DeleteOnClose属性

    实验结果:关闭testWidget窗口后,调用了其析构函数,内存被释放了

    改进方法B

    不设置Qt::WA_DeleteOnClose属性,但是在new完testWidget后,程序退出前调用testWidget的delete函数

    实验结果:关闭testWidget窗口后,调用了其析构函数,内存也被释放了

    实验结论:QWidget及其派生类的对象,可以设置 Qt::WA_DeleteOnClose 标志位(当close时会析构该对象)或者手动delete来释放内存

    栈空间的内存实践实例不采用new,为testWidget分配栈空间,不设置Qt::WA_DeleteOnClose属性,不手动delete

    实验结果:关闭窗口时调用了testWidget的析构函数,内存被释放了

    testWidget不采用new创建,直接将对象建议在栈空间,但设置Qt::WA_DeleteOnClose属性或者使用后delete &testWidget

    实验结果:程序崩溃了,在第一次尝试delete testWidget时就出错

    实验结论:delete栈上分配的地址会出错

    父对象和子对象析构的实践实例将testWidget的父对象设置为mainwindow

    实验结果:关闭窗口后,正常打印析构信息。程序退出前,先释放testWidget的空间,再释放mainwindow的空间(两者都是分配到栈空间)

    调整mainwindow和testWidget的构造顺序

    实验结果:程序崩溃

    分析原因:mainwindow析构时会将其子对象testWidget也析构,但testWidget是分配到栈空间上的,delete栈上的空间会出错。

    将testWidget分配到堆上,指定父对象为mainwindow,并在程序退出前delete mainwindow

    实验结果:delete mainwindow时,会将testWidget也一并delete

    将testWidget作为mainwindow的成员,但在构造时不指定父对象,在main函数中delete mainwindow

    实验结果:应用程序退出前只有mainwindow被析构了

    实验结论:

    • 析构函数总是出现在对象的生命期结束之时,静态对象在程序运行结束之时析构。

    • 对象的构造和析构的关系是栈数据结构中的入栈和出栈的关系。

    • 指定了父对象的子对象,在父对象被析构时,会将其一并析构掉

    Malloc分配的内存空间实践实例

    新建一个malloc_class,将malloc_class作为mainwindow的成员,在mallocClass的构造函数里面用malloc申请500M内存,在mainwindow放置一个button,点击button就delete malloc_class,在任务管理器中看500M内存是否有被释放。对于malloc_class的new操作,测试了两种情况:

    new malloc_class时不指定父对象new malloc_class时指定它的父对象为mainwindow

    实验结果:两种情况一样的结果,点击button,在delete testWidget后,在testThread中申请的500M空间都没有被释放

    猜想是不是因为malloc的空间并没有指定父对象,异想天开的又测试了另外一种情况:直接创建malloc_class时用malloc为其分配内存,再在button的槽函数里delete malloc_class

    实验结果:程序崩溃了……

    查阅资料得知:malloc只能为POD类型数据(一个类或结构体通过二进制拷贝后还能保持数据不变,具体解释自查资料)分配内存,其他的必须用new分配内存。Malloc函数分配内存空间时并不调用构造函数,同样free函数再回收空间时也不调用析构函数。

    实验结论:malloc分配的内存空间都要自己管理,与QT的父子对象同步析构没有关系。也就是说应该再次明确:指定父对象的并且基于QObject为基类的对象才会同步析构

    注意:malloc的空间只是一个虚拟内存,一定要初始化或者写数据才会有物理内存的体现

    对于在应用程序中不是常驻的对象,应习惯为其指定父对象,或着用完之后手动delete;对于应用程序中常驻的对象,即便在应用程序结束后操作系统会释放其使用的内存,也不建议随性new没有parent的对象。总之,养成严格处理内存分配和释放内存的好习惯,要清楚自己在编码时使用了哪些内存,什么时候需要释放,不定时关注程序的内存占用率。

    看完上述内容,你们掌握如何解决QT内存泄漏的问题的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注行业资讯频道,感谢各位的阅读!

    对象 内存 空间 实验 程序 函数 结果 分配 问题 属性 方法 实例 应用程序 成员 数据 时候 结论 实践 应用 管理 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 华服互联网科技靠谱吗 唐信互联网科技 艾特科技互联网 北京互联网络科技有限公司 互联网 科技馆 成都玖崟互联网科技有限公司乐商圈怎么样 互联网科技寓意 移动互联网科技股 茂名市互联网科技产业园 世界互联网科技公司市值排名 昭通互联网科技选哪家 宝灵互联网科技有限公司 哈尔滨屹滨互联网科技有限公司 互联网科技研发水平 互联网科技创新的路径 中科明德北京互联网科技 同城互联网络科技 北京天晋互联网科技有限公司 上海互联网科技园景观 宁波允成互联网科技有限公司 亿人帮互联网科技有限公司 互联网是第几次科技革命的成果 互联网核心科技是什么 易互联网科技有限公司 互联网金融 科技金融 济南和联互联网科技有限公司 华夏恒生科技与互联网科技 21世纪互联网科技成就 全球科技与互联网公司市值变化 互联网高科技绘画
    0