Qt的内存释放策略(内存自动释放机制)

总结一下Qt内存泄漏检测与处理策略,并附个人写的C++单例类,用于内存自动释放 1、Qt中控件new之后需不需要delete的问题 https://blog.youkuaiyun.com/Aidam_Bo/article/details/86303096 * QT的父子对象机制是在 QWidget和QOject中实现的。当我们使用父对象来创建一个对象的时候 , * 父对象会把这个对象添加到自己的子对象列表中。当这个父对象被删除的时候,它会遍历它的子对象类表并且删除每一个子对象, * 然后子对象们自己再删除它们自己的子对象,这样递归调用直到所有对象都被删除。 * 这种父子对象机制会在... 阅读详情

原文地址:http://www.cnblogs.com/foxhengxing/archive/2010/12/24/1916355.html


很多C/C++初学者常犯的一个错误就是,使用malloc、new分配了一块内存却忘记释放,导致内存泄漏。Qt的对象模型提供了一种Qt对象之间的父 子关系,当很多个对象都按一定次序建立起来这种父子关系的时候,就组织成了一颗树。当delete一个父对象的时候,Qt的对象模型机制保证了会自动的把 它的所有子对象,以及孙对象,等等,全部delete,从而保证不会有内存泄漏的情况发生。

任何事情都有正反两面作用,这种机制看上去挺好,但是却会对很多Qt的初学者造成困扰,我经常给别人回答的问题是:1,new了一个Qt对象之后,在什么 情况下应该delete它?2,Qt的析构函数是不是有bug?3,为什么正常delete一个Qt对象却会产生segment fault?等等诸如此类的问题,这篇文章就是针对这个问题的详细解释。

在每一个Qt对象中,都有一个链表,这个链表保存有它所有子对象的指针。当创建一个新的Qt对象的时候,如果把另外一个Qt对象指定为这个对象的父对象, 那么父对象就会在它的子对象链表中加入这个子对象的指针。另外,对于任意一个Qt对象而言,在其生命周期的任何时候,都还可以通过setParent函数 重新设置它的父对象。当一个父对象在被delete的时候,它会自动的把它所有的子对象全部delete。当一个子对象在delete的时候,会把它自己 从它的父对象的子对象链表中删除。

QWidget是所有在屏幕上显示出来的界面对象的基类,它扩展了Qt对象的父子关系。一个Widget对象也就自然的成为其父Widget对象的子 Widget,并且显示在它的父Widget的坐标系统中。例如,一个对话框(dialog)上的按钮(button)应该是这个对话框的子 Widget。

关于Qt对象的new和delete,下面我们举例说明。

例如,下面这一段代码是正确的:

int main()
{
QObject* objParent = new QObject(NULL);
QObject* objChild = new QObject(objParent);
QObject* objChild2 = new QObject(objParent);
delete objParent;
}

我们用一张图来描述这三个对象之间的关系:

clip_image001

在上述代码片段中,objParent是objChild的父对象,在objParent对象中有一个子对象链表,这个链表中保存它所有子对象的指针,在 这里,就是保存了objChild和objChild2的指针。在代码的结束部分,就只有delete了一个对象objParent,在objParent对象的析构函数会遍历它的子对象链表,并且把它所有的子对象(objChild和objChild2)一一删除。所以上面这段代码是安 全的,不会造成内存泄漏。

如果我们把上面这段代码改成这样,也是正确的:

int main()

{

QObject* objParent = new QObject(NULL);

QObject* objChild = new QObject(objParent);

QObject* objChild2 = new QObject(objParent);

delete objChild;

delete objParent;

}

在这段代码中,我们就只看一下和上一段代码不一样的地方,就是在delete objParent对象之前,先delete objChild对象。在delete objChild对象的时候,objChild对象会自动的把自己从objParent对象的子对象链表中删除,也就是说,在objChild对象被 delete完成之后,objParent对象就只有一个子对象(objChild2)了。然后在delete objParent对象的时候,会自动把objChild2对象也delete。所以,这段代码也是安全的。

Qt的这种设计对某些调试工具来说却是不友好的,比如valgrind。比如上面这段代码,valgrind工具在分析代码的时候,就会认为objChild2对象没有被正确的delete,从而会报告说,这段代码存在内存泄漏。哈哈,我们知道,这个报告是不对的。

我们在看一看这一段代码:

int main()

{

QWidget window;

QPushButton quit("Exit", &window);

}

在这段代码中,我们创建了两个widget对象,第一个是window,第二个是quit,他们都是Qt对象,因为QPushButton是从QWidget派生出来的,而QWidget是从QObject派生出来的。这两个对象之间的关系是,window对象是quit对象的父对象,由于他们 都会被分配在栈(stack)上面,那么quit对象是不是会被析构两次呢?我们知道,在一个函数体内部声明的变量,在这个函数退出的时候就会被析构,那 么在这段代码中,window和quit两个对象在函数退出的时候析构函数都会被调用。那么,假设,如果是window的析构函数先被调用的话,它就会去 delete quit对象;然后quit的析构函数再次被调用,程序就出错了。事实情况不是这样的,C++标准规定,本地对象的析构函数的调用顺序与他们的构造顺序相 反。那么在这段代码中,这就是quit对象的析构函数一定会比window对象的析构函数先被调用,所以,在window对象析构的时候,quit对象已 经不存在了,不会被析构两次。

如果我们把代码改成这个样子,就会出错了,对照前面的解释,请你自己来分析一下吧。

int main()

{

QPushButton quit("Exit");

QWidget window;

quit.setParent(&window);

}

但是我们自己在写程序的时候,也必须重点注意一项,千万不要delete子对象两次,就像前面这段代码那样,程序肯定就crash了。

最后,让我们来结合Qt source code,来看看这parent/child关系是如何实现的。

在本专栏文章的第一部分“对象数据存储”,我们说到过,所有Qt对象的私有数据成员的基类是QObjectData类,这个类的定义如下:

typedef QList<QObject*> QObjectList;

class QObjectData

{

public:

QObject *parent;

QObjectList children;

// 忽略其它成员定义

};

我们可以看到,在这里定义了指向parent的指针,和保存子对象的列表。其实,把一个对象设置成另一个对象的父对象,无非就是在操作这两个数据。把子对 象中的这个parent变量设置为指向其父对象;而在父对象的children列表中加入子对象的指针。当然,我这里说的非常简单,在实际的代码中复杂的 多,包含有很多条件判断,有兴趣的朋友可以自己去读一下Qt的源代码。

Qt消息框自动关闭的3个坑,我帮你踩过了(附QTimer使用避坑指南) 本文深入探讨了Qt开发中实现消息框自动关闭时常见的3个问题,包括QTimer内存泄漏、父窗口变化导致的位置错乱以及定时器精度问题。通过详细的代码示例和解决方案,帮助开发者避开这些陷阱,特别是提供了QTimer的最佳使用实践,确保消息提示框的稳定性和精确性。 阅读详情

相关推荐

Qt中的内存泄漏

作者:billy 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 https://blog.youkuaiyun.com/weixin_34166472/article/details/92651322 https://blog.youkuaiyun.com/envenler/article/details/8020064 https://blog.youkuaiyun.com/u013711616/a...

billy的博客 4894

malloc---动态内存分配函数

malloc

weixin_48651223的博客 1600

Qt QList清空问题

1.代码分析 //向QList中添加4个项 QList<QWidget*> lstWidget; lstWidget.append(new QWidget); lstWidget.append(new QWidget); lstWidget.append(new QWidget); lstWidget.append(new QWidget); 情况1: 采用foreach遍历...

希望能帮助大家,希望大家多多支持,你们的支持是我前进的动力。 1万+

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

Qt内存管理机制:Qt 在内部能够维护对象的层次结构。对于可视元素,这种层次结构就是子组件与父组件的关系;对于非可视元素,则是一个对象与另一个对象的从属关系。在 Qt 中,在 Qt 中,删除父对象会将其子对象一起删除。 C++中delete 和 new 必须配对使用(一 一对应):delete少了,则内存泄露,多了麻烦更大。Qt中使用了new却很少delete,因为QObject的类及其继承的类,设置了parent(也可在构造时使用setParent函数或parent的addChild)故p

乌托邦 4万+

Qt基础篇:Qt的内存释放策略(内存自动释放机制)

关于Qt内存释放机制的简单讲解 很多C/C++初学者常犯的一个错误就是,使用malloc、new分配了一块内存却忘记释放,导致内存泄漏。Qt的对象模型提供了一种Qt对象之间的父 子关系,当很多个对象都按一定次序建立起来这种父子关系的时候,就组织成了一颗树。当delete一个父对象的时候,Qt的对象模型机制保证了会自动的把 它的所有子对象,以及孙对象,等等,全部delete,从而保证不会有内存泄漏的情况发生。 任何事情都有正反两面作用,这......

欧特GO 5967

KiCad自动布线实战:FreeRouting插件安装与使用指南

在PCB设计流程中,布线环节往往占据大量重复性工作,尤其对于中小型双面板,成百上千条飞线的手动连接既繁琐又易出错。自动布线技术通过算法在给定设计规则和元件布局的基础上自动规划走线路径,能显著提升布线效率。FreeRouting作为一款开源自动布线器,与KiCad通过DSN/SES标准中间格式无缝配合,让工程师将精力集中于关键信号和布局优化,而将常规网络交给工具处理。本文从自动布线的原理与边界出发,讲解了FreeRouting的安装、DSN导出、参数设置、自动布线及结果回传的完整流程,并结合实际案例展示了在S

weixin_32025789的博客 278

Qt中QSharedMemory析构处理指南

Qt中QSharedMemory析构处理指南

xie__jin__cheng的博客 422

SAP子公司财务账套配置实战:从公司代码到记账期间变式的关键步骤

本文详细介绍了为SAP子公司快速配置财务账套的实战步骤。通过复用母公司成熟配置,重点阐述了从创建公司代码、关联控制范围到分配记账期间变式的核心流程,帮助顾问在一两个小时内完成核心骨架搭建,实现高效集团财务管控。

cake8的博客 165

Qt 的对象树内存管理机制及实现原理

Qt对象树内存管理机制通过父子对象关系自动管理内存生命周期。当父对象被销毁时,会自动递归删除所有子对象,避免内存泄漏。核心原理是QObject内部维护父指针和子对象列表,在析构函数中自动清理子对象。该机制简化了GUI程序中大量控件的内存管理,尤其适用于QWidget及其子类,同时确保不会重复删除。开发者只需在创建对象时指定父对象,无需手动释放,提高了代码的安全性和简洁性。

编程改变世界。想做一些改变世界的产品。感谢一键三连。 378

Nano Banana 2哪里使用?Nano Banana 2提示词合集和使用教程

收集最强的Nano Banana 2提示词合集,以及Nano Banana 2哪里使用的教程,并且有10个免费使用渠道。

qq_42927225的博客 1988

kaggle:Digit Recognizer《手写数字识别》你的第一个图像识别竞赛项目

新手,入门,巩固复习,深度学习,图像识别

qq_63591092的博客 3097

QTabWidget隐藏Tab页踩坑记录:为什么removeTab后控件还在内存里?

本文深入解析了Qt开发中QTabWidget调用removeTab方法后控件仍驻留内存的问题。通过剖析Qt对象树机制,揭示了removeTab不会自动删除页面的本质,并提供了手动删除、QPointer智能指针及RAII自动管理等多种解决方案,帮助开发者有效避免内存泄漏,构建更健壮的应用程序。

d6e7f8的博客 698

C# ArcGIS Engine二次开发——实现“加载shp文件”

private void AddShpDataToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog OpFileDialog=new OpenFileDialog();//OpenFileDialog:打开文件对话框 OpFileDialog.Title="添加矢量数据"; OpFileDialog.Filter="(*.shp)|*.shp";//filter:过滤器;"(*.shp)|*.shp"

weixin_42191203的博客 5254

GoQt内存管理详解:避免Go与C++内存交互的常见陷阱

GoQt作为Golang与Qt跨平台应用框架的绑定库,其内存管理涉及Go的自动垃圾回收与C++的手动内存管理双重机制。本文将系统讲解GoQt内存管理的核心原理、常见陷阱及最佳实践,帮助开发者写出更安全、高效的跨平台应用。 ## QObject对象树:理解Qt的父子关系管理 QObject及其派生类(如QWidget、QAction)采用**对象树**内存管理模式。当创建QObject时指定父对

gitblog_00800的博客 362

DO-254标准详解:航空电子硬件设计保证指南全方位解析

RTCA DO-254, 也被称为《机载电子硬件设计保证指南》,是航空电子硬件设计和验证中的关键标准,旨在为确保机载电子硬件的安全性提供设计保证。自2000年首次发布以来,DO-254就成为了民航和军用飞机中电子硬件设计认证的基准文件。随着航空硬件技术的进步和日益复杂化,确保硬件设计的准确性、可靠性和安全性变得至关重要。本标准是由RTCA和EUROCAE共同开发的,适用于涉及机载硬件的航空公司、飞机制造商、供应商和认证机构。

qq_41854911的博客 3682

华为OD机试 - 字符串筛选排序 - 数组(Python/JS/C/C++ 双机位C卷 100分)

k如果大于字符串长度则输出最大ASCII码值的字母所在字符串的位置索引,如果第k个最小ASCII码值的字母存在重复 则输出该字母的最小位置索引。输入一个由N个大小写字母组成的字符串,按照ASCII码值从小到大进行排序,查找字符串中第K个最小ASCII码值的字母(k>=1)。k如果大于字符串长度则输出最大ASCII码值的字母所在字符串的位置索引,如果有重复字母则输出字母的最小位置索引。输出字符串中第k个最小ASCII码值的字母所在字符串的位置索引。第二行输入k ,k必须大于0 ,k可以大于输入字符串的长度。

学Java,找哪吒 1391

PySide6从0开始学习的笔记(二十五) Qt对象的生命周期和及时销毁

正如之前学习过的,当Qt的窗口对象被关闭(close())之后,它并没有在内存中消失,只是暂时隐藏起来不显示,当再次执行show()就会显示。对于一些短时间运行的简单小应用,这种重复生成并且不被销毁的对象,不会对系统资源有多大的消耗,但如果是一个7*24h运行,频繁操作的应用,比如工业视觉检测、scada项目等,就不得不重视对象的生命周期,对于不再有用的对象要及时销毁,以免对系统资源带来浪费。但是,只有点击"关闭本窗口按钮“关闭窗口,才能销毁,如果使用窗口右上角自带的关闭按钮关闭窗口,仍然不会被销毁。

xulibo5828的博客 410

RK3588开发笔记-mipi csi接口imx415摄像头调试记录

摘要:本文详细介绍了RK3588开发板适配SONY IMX415 MIPI CSI摄像头的调试过程。从硬件环境准备(包括RK3588核心板、IMX415模块连接及测试工具)、软件环境配置(Linux 5.10内核、驱动状态确认),到设备树关键配置(MIPI链路、GPIO引脚、电源域等)都进行了详细说明。调试过程中通过dmesg日志、media-ctl拓扑分析等工具验证了摄像头驱动加载和图像采集功能。最终实现了800万像素高清图像采集,总结了硬件连接验证、信号完整性优化等关键经验,为类似MIPI摄像头调试提供

flypig has a dream! 882

QT C++ TCP服务器端网络通信源码深度解析与实战指南

网络通信是分布式系统和客户端-服务器应用的基础,其核心在于建立可靠的数据传输通道。TCP协议通过三次握手、流量控制和重传机制保证了数据的可靠、有序交付,是构建稳定网络服务的基石。在C++开发领域,利用成熟的框架可以高效实现这一目标,其中QT框架以其强大的信号与槽机制和跨平台能力,为网络编程提供了优雅的异步事件驱动模型。这带来了显著的技术价值:开发者无需直接处理复杂的底层I/O多路复用(如epoll),即可构建出支持高并发连接的服务器,极大地提升了开发效率和程序的可维护性。此类技术广泛应用于即时通讯、物联网设

weixin_30335353的博客 374

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

嵌入式Qt中qtimer::singleshot的系统学习路径

从信号槽机制出发,手把手带你掌握QTimer::singleShot在嵌入式Qt开发中的核心应用场景:延时执行、资源释放与事件解耦。结合定时精度、线程安全和内存管理要点,避开常见陷阱,让延时逻辑更健壮、更轻量。

weixin_32535825的博客 322

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

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

转载,原文链接:https://blog.youkuaiyun.com/libaineu2004/article/details/106771500 如果时间急迫,不想看完整文章,可以直接去到文章末尾,看结论。有我个人写的C++单例类,用于内存自动释放。 1、QtCreator编写C++代码,怎么检测内存泄漏? 请参见本人的另一篇博文:https://blog.youkuaiyun.com/libaineu2004/article/details/104071627 2、Qt中控件new之后需不需要delete的问题 https:

VectorAL的博客 5618

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

【Qt底层之内存管理机制】Qt 对象 父子关系、运行时机制与高效编程技巧

内存管理是计算机程序设计中的一个关键领域,特别是在C++这种提供了底层内存控制能力的语言中。Qt框架的内存管理机制独特且强大,它采用了一种称为“父子关系”(Parent-Child Relationship)的策略来管理对象的生命周期。这种策略有效地简化了内存管理,降低了内存泄漏的风险。

探索C++编程的奥秘,分享深入的技术见解和实践,旨在激发读者创造力与解决问题的思维。 2388

qt 如何 指针 自动 释放内存_iOS 内存管理相关面试题

内存管理的一些概念1.1 为什么要使用内存管理?严格的内存管理,能够是我们的应用程在性能上有很大的提高如果忽略内存管理,可能导致应用占用内存过高,导致程序崩溃1.2 OC的内存管理主要有三种方式:ARC(自动内存计数)手动内存计数内存池1.3 OC中内存管理的基本思想:保证任何时候指向对象的指针个数和对象的引用计数相同,多一个指针指向这个对象这个对象的引用计数就加1,少一个指针指向这个对...

weixin_39637646的博客 318
上一篇: oracle dbf文件更换目录
下一篇: mybase7.0激活方法
Maybe______
博客等级 码龄10年 26粉丝 13原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值