【QT】关于Qt::WA_DeleteOnClose的使用问题

2024-03-27 22:18

本文主要是介绍【QT】关于Qt::WA_DeleteOnClose的使用问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今天在解决软件bug的过程中,注意到QT关于[slot] bool QWidget::close()有这样一段说明:

If the widget has the Qt::WA_DeleteOnClose flag, the widget is also deleted. A close events is delivered to the widget no matter if the widget is visible or not.

逆向思考,如果我的QWidget或继承于QWidget的派生类没有设置相关的flag:Qt::WA_DeleteOnClose,那么他是不会自动析构的。情况真是如此吗?

测试环境:
macOS Mojave 10.14
Qt Creator 4.41
Qt 5.9.2
Clang 7.0 apple, 64 bits

场景一: 独立widget,没有flag Qt::WA_DeleteOnClose

widget.cpp

#include "widget.h"
#include "ui_widget.h"#include <QDebug>Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);
}Widget::~Widget()
{delete ui;qDebug() << "Widget::~Widget()";
}void Widget::on_pushButton_clicked()
{close(); //output: Widget::~Widget()
}

main.cpp

#include "widget.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

widget.ui:

在这种情况下,不设置flag QT::WA_DeleteOnClose,我们依然可用通过函数链:Widget::on_pushButton_clicked => Widget::close 来触发析构函数。
那么QT关于此flag的说明到底是什么意思呢?接着看下面的场景。

场景二: 自定义的widget作为其他widget的child widget,没有flag Qt::WA_DeleteOnClose

现在widget.ui文件设置成这样:

main.cpp

#include "widget.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);QWidget parentW;parentW.show();Widget w(&parentW);w.show();setbuf( stdout, NULL );return a.exec();
}

qwidget.cpp

#include "widget.h"
#include "ui_widget.h"#include <QDebug>Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);printf( "this: %p\n", this );printf( "ui: %p\n", ui );
}Widget::~Widget()
{delete ui;qDebug() << "Widget::~Widget()";
}void Widget::on_pushButton_clicked()
{qDebug() << testAttribute( Qt::WA_DeleteOnClose );close();
}

一开始显示:

然后我们点击button,button消失。输出:

this: 0x7ffeed17e9e0
ui: 0x7faaacd12c40
false

析构函数没有被调用。

场景三: 自定义的widget作为其他widget的child widget,有flag Qt::WA_DeleteOnClose

在场景二的基础上,Widget的构造函数中加上:

setAttribute( Qt::WA_DeleteOnClose, true );

运行,再点击button,我们得到:

this: 0x7ffee5578a28
ui: 0x7fc99ef14f70
true
Widget::~Widget()
The program has unexpectedly finished.
The process was ended forcefully.

系统报错:error for object 0x7ffee5578a28: pointer being freed was not allocated
也就说,函数链:Widget::on_pushButton_clicked => Widget::close触发了一次析构函数,后面widget的对象又被析构了一次。
注意到我们的Widget对象在main.cpp中是分配到栈内存的,所以在main函数结束后,系统会尝试析构我们的Widget对象。
在qwidget.cpp我们能找到这样的语句:

8442      if (!that.isNull()) {
8443           data.is_closing = 0;
8444           if (q->testAttribute(Qt::WA_DeleteOnClose)) {
8445              q->setAttribute(Qt::WA_DeleteOnClose, false);
8446              q->deleteLater();
8447           }
8448      }
8449      return true;
8450 }

接着,将Widget对象从堆里申请内存,就不会存在多次释放内存的问题了。
main.cpp

Widget *w = new Widget(&parentW);
w->show();

点击红色的button之后:

总结:Qt::WA_DeleteOnClose用于申请堆内存的QWidget对象,并有通过close方法释放内存的需求的场景。

这篇关于【QT】关于Qt::WA_DeleteOnClose的使用问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/853560

相关文章

k8s容器放开锁内存限制问题

《k8s容器放开锁内存限制问题》nccl-test容器运行mpirun时因NCCL_BUFFSIZE过大导致OOM,需通过修改docker服务配置文件,将LimitMEMLOCK设为infinity并... 目录问题问题确认放开容器max locked memory限制总结参考:https://Access

在Android中使用WebView在线查看PDF文件的方法示例

《在Android中使用WebView在线查看PDF文件的方法示例》在Android应用开发中,有时我们需要在客户端展示PDF文件,以便用户可以阅读或交互,:本文主要介绍在Android中使用We... 目录简介:1. WebView组件介绍2. 在androidManifest.XML中添加Interne

Java中字符编码问题的解决方法详解

《Java中字符编码问题的解决方法详解》在日常Java开发中,字符编码问题是一个非常常见却又特别容易踩坑的地方,这篇文章就带你一步一步看清楚字符编码的来龙去脉,并结合可运行的代码,看看如何在Java项... 目录前言背景:为什么会出现编码问题常见场景分析控制台输出乱码文件读写乱码数据库存取乱码解决方案统一使

Java Stream流与使用操作指南

《JavaStream流与使用操作指南》Stream不是数据结构,而是一种高级的数据处理工具,允许你以声明式的方式处理数据集合,类似于SQL语句操作数据库,本文给大家介绍JavaStream流与使用... 目录一、什么是stream流二、创建stream流1.单列集合创建stream流2.双列集合创建str

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

Spring Security简介、使用与最佳实践

《SpringSecurity简介、使用与最佳实践》SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,本文给大家介绍SpringSec... 目录一、如何理解 Spring Security?—— 核心思想二、如何在 Java 项目中使用?——

springboot中使用okhttp3的小结

《springboot中使用okhttp3的小结》OkHttp3是一个JavaHTTP客户端,可以处理各种请求类型,比如GET、POST、PUT等,并且支持高效的HTTP连接池、请求和响应缓存、以及异... 在 Spring Boot 项目中使用 OkHttp3 进行 HTTP 请求是一个高效且流行的方式。

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结