未使用 `deleteLater` 而直接使用 `delete` 导致问题

news/2024/11/16 12:22:56/文章来源:https://www.cnblogs.com/DesertCactus/p/18549249

以下是一个完整的Qt代码示例,展示了未使用 deleteLater 而直接使用 delete 导致问题的情况,该示例涉及到一个简单的多线程场景,主线程创建一个工作线程,工作线程完成任务后通知主线程,在对象删除处理不当的情况下会出现崩溃等问题。

示例代码

#include <QObject>
#include <QThread>
#include <QDebug>
#include <QCoreApplication>// 工作类,继承自QObject,用于在工作线程中执行任务
class Worker : public QObject
{Q_OBJECT
public:Worker() {}signals:// 任务完成后发送信号,传递一个整数值给主线程void resultReady(int result);public slots:void doWork(){// 模拟耗时任务,这里简单睡眠一下QThread::sleep(2);int result = 42;// 发送任务完成的信号emit resultReady(result);}
};// 控制器类,用于管理工作线程和处理结果
class Controller : public QObject
{Q_OBJECT
public:Controller(){// 创建工作对象和线程对象worker = new Worker();thread = new QThread();// 将工作对象移动到工作线程中worker->moveToThread(thread);// 连接线程启动信号和工作对象的工作函数connect(thread, &QThread::started, worker, &Worker::doWork);// 连接工作对象的完成信号和自身的处理结果函数connect(worker, &Worker::resultReady, this, &Controller::handleResult);// 启动线程thread->start();}~Controller(){// 这里直接delete工作对象,会导致问题,应该使用worker->deleteLater()delete worker;thread->quit();thread->wait();delete thread;}private slots:void handleResult(int result){qDebug() << "Received result: " << result;}private:Worker *worker;QThread *thread;
};int main(int argc, char *argv[])
{QCoreApplication app(argc, argv);{Controller controller;}return app.exec();
}#include "main.moc"

问题分析

在上述代码中,Controller 类负责管理工作线程和处理工作线程返回的结果。在 Controller 的析构函数中,直接使用 delete 来删除 worker 对象存在以下严重问题:

  • 对象生命周期冲突
    Controller 的析构函数被调用时(例如在 main 函数中 Controller 实例所在的作用域结束时),如果此时工作线程中的 worker 对象还在执行 doWork 函数(比如还处于 QThread::sleep(2) 的睡眠阶段或者刚结束睡眠正准备发送 resultReady 信号),直接调用 delete 去删除 worker 对象,就违背了对象的正常生命周期。因为 worker 对象在工作线程中仍处于活动状态,其内部资源还在被使用,这样强制删除会导致工作线程后续可能对已经释放的内存进行访问(例如尝试去发送 resultReady 信号时,相关的对象内存已经不存在了),从而引发程序崩溃,一般会出现类似“段错误”的报错提示。

  • 线程安全问题
    由于是在多线程环境下,主线程(也就是 Controller 所在的线程,执行析构函数的线程)直接删除了 worker 对象,而工作线程并不知道这个情况,这就造成了线程间的同步问题。如果工作线程后续继续按照正常流程去操作 worker 对象(比如触发信号等),就会出现对非法内存区域的访问,破坏了多线程编程中对共享对象访问的安全性要求,导致程序出现未定义行为甚至崩溃。

正确的做法应该是在合适的时机调用 worker->deleteLater(),例如可以在 handleResult 槽函数中判断任务已经彻底完成,不会再有对 worker 对象的操作后,调用 worker->deleteLater() 来安全地安排 worker 对象的删除,让Qt的事件循环在确保安全的情况下(比如工作线程相关的所有操作都完成后)再执行删除操作,避免上述出现的各种问题,保障程序的稳定运行。

希望这个示例能够清晰地展示未合理使用 deleteLater 所带来的问题,你如果还有其他疑问或者想进一步了解相关知识,可以随时问我。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/834542.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

本地oracle数据库实例启动报错 TNS-12545 TNS-12560 TNS-00515

oracle 实例启动报错 TNS-12545 TNS-12560 TNS-00515 具体提示如下: 监听该对象时出错: (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=host.docker.internal)(PORT=1521))) TNS-12545: 因目标主机或对象不存在, 连接失败 TNS-12560: TNS: 协议适配器错误 TNS-00515: 因目标主机…

jenkinsfile

k8s集群中用的jenkinsfile部署 java后台项目# x项目 test-java-eladmin-ci// harbor镜像仓库地址和密码信息 def registry = "harbor.solomon.com" // jenkins中定义的连接harbor的用户名密码凭据 def registry_se = "d2318c77-8a32-4618-bced-d6cabb0454b4&quo…

[网鼎杯 2018]Fakebook 1

[网鼎杯 2018]Fakebook 1 打开实例发现为博客列表,有登录跳转和类似注册或者添加博客的join跳转查看源码无果 打开登陆页,尝试万能密码没有用,尝试从join入手,用admin去随便join一个显示博客不存在 期间尝试多种sql注入方法均没有效果,转去其他方向 尝试dirsearch目录爆破…

【Adobe Premiere pro 2025下载与安装教程】

1、安装包「Adobe Premiere Pro 2025」: 链接:https://pan.quark.cn/s/e93beb96accb 提取码:CGY2 2、安装教程 1) 下载软件安装包,打开安装目录,双击Setup.exe安装,弹出安装对话框2) 选择安装目录,尽量不要选C盘,点击继续3) 等待安装过程完成,点…

人工智能同样也会读死书----“过拟合”

上一篇:《“嵌入”在大语言模型中是解决把句子转换成向量表示的技术》 序言:我们常常会说某某人只会“读死书”,题目稍微变一点就不会做了。这其实是我们人类学习中很常见的现象。可是你知道吗?人工智能其实更容易“读死书”。不过在人工智能领域,我们有个听起来高大上的说…

D45XT80-ASEMI电机专用整流桥D45XT80

D45XT80-ASEMI电机专用整流桥D45XT80编辑:ll D45XT80-ASEMI电机专用整流桥D45XT80 型号:D45XT80 品牌:ASEMI 封装:DXT-5 特性:插件桥堆 正向电流:45A 反向耐压:800V 恢复时间:>2000ns 引脚数量:5 芯片个数:4 芯片尺寸:50MIL 浪涌电流:450A 漏电流:>10uA 工作温…

【Adobe Acrobat pro 2024软件下载与安装教程-PDF编辑神奇】

1、安装包 「Adobe Acrobat 2024」: 链接:https://pan.quark.cn/s/86f8683afe5c 提取码:4uur 2、安装教程(建议关闭杀毒软件和系统防护) 1) 下载软件安装包,打开安装目录,双击Setup.exe安装,弹出安装对话框2) 点击安装按钮3) 正在安装4) 安装…

书生共学大模型训练营第4期 L1G200任务提交

MindSearch搜索引擎示例书生浦语对话模型调用示例书生万象开源视觉语言模型调用实例进阶任务:MindSearch话题挑战 https://www.zhihu.com/people/zhang-shu-yang-92-96

使用nvm管理多版本node的详细教程

在开发工作中,经常在不同的项目中使用不同版本的node去开发,换一个项目在重新安装node太麻烦,所以使用nvm来管理多版本的node开发环境,就非常方便了,所以本文给大家介绍了如何使用nvm管理多版本node,需要的朋友可以参考下前言 在开发工作中,经常在不同的项目中使用不同版本的n…

Metasploit Pro 4.22.5-2024111401 (Linux, Windows) - 专业渗透测试框架

Metasploit Pro 4.22.5-2024111401 (Linux, Windows) - 专业渗透测试框架Metasploit Pro 4.22.5-2024111401 (Linux, Windows) - 专业渗透测试框架 Rapid7 Penetration testing, released Nov 14, 2024 请访问原文链接:https://sysin.org/blog/metasploit-pro-4/ 查看最新版。…

.ts文件和d.ts文件对比

TS中有俩种文件类型,一种是.ts文件,一种是.d.ts文件 .ts文件 既可以包含类型信息也可以写逻辑代码 可以被编译为js文件 .d.ts文件 只能包含类型信息不可以写逻辑代码 不会被编译为js文件,仅做类型校验检查 自定义类型声明文件 d.ts文件在项目中是可以进行自定义创建的,通常…

Ubuntu Server 20.04 安装MySQL

1. 通过apt安装MySQL1 #命令1 2 sudo apt-get update 3 #命令2 4 sudo apt-get install mysql-server2. 配置mysql初始化信息1 sudo mysql_secure_installation配置说明:ubuntu@VM-0-10-ubuntu:~$ sudo mysql_secure_installationSecuring the MySQL server deployment.Connec…