QModbusTCPClient 服务器断开引起的程序崩溃
最近使用QModbusTCPClient 与一套设备通信,有一个QTimer频繁的通过读取设备寄存器。程序运行良好,但是有个问题:正常进行中设备断电了,整个程序都会崩溃。解决过程如下:
1.失败方案一
在QModbusTCPClient的errorOccurred()信号中判断错误后及时关闭QTimer,避免出错之后还要频繁访问。
此方案失败,问题不在这里。
2.失败方案二
m_reply= m_modbus->sendReadRequest(m_unit[1], m_outputID);if(m_reply && !m_reply->isFinished()){connect(m_reply, &QModbusReply::finished, [this]() {if(m_reply->error() == QModbusDevice::NoError){m_outputs = m_reply->result().values();}m_modbus->disconnect(SIGNAL(timeoutChanged(int)), 0, 0);delete m_reply;m_reply = nullptr;});}
一个典型的应用如上。对 QModbusTCPClient发送读写请求后,会得到一个QModbusReply指针,根据QModbusReply的finished信号判断请求结果。这个过程是异步的,所以上面的及时停止QTimer并不能真的“及时”停止。
在finished的响应槽函数中判断一下error状态,再进行后面的操作,仍然失败。
3.方案三(有点眉目)
m_reply= m_modbus->sendReadRequest(m_unit[1], m_outputID);if(m_reply && !m_reply->isFinished()){connect(m_reply, &QModbusReply::finished, [this]() {});}
直接把这个函数体变成空的,什么也不做,发现程序不崩溃了。问题范围成功缩小。于是对函数体中的逐行打印,看看到底哪一步崩溃的。
m_reply= m_modbus->sendReadRequest(m_unit[1], m_outputID);if(m_reply && !m_reply->isFinished()){connect(m_reply, &QModbusReply::finished, [this]() {
qDebug()<<1;if(m_reply->error() == QModbusDevice::NoError){
qDebug()<<2;m_outputs = m_reply->result().values();}
qDebug()<<3;m_modbus->disconnect(SIGNAL(timeoutChanged(int)), 0, 0);
qDebug()<<4;delete m_reply;
qDebug()<<5;m_reply = nullptr;});}
结果发现只要对m_reply进行访问,就会崩溃。
4.方案四(部分解决)
在reply的finished信号响应函数中为啥不能访问reply呢,打印一下reply看看啥情况。
m_reply= m_modbus->sendReadRequest(m_unit[1], m_outputID);if(m_reply && !m_reply->isFinished()){connect(m_reply, &QModbusReply::finished, [this]() {qDebug()<<m_reply;});}
一旦QModbus设备断电,reply竟然是空值!!!!
QModbusReply(0x232d1d5de40)
QModbusReply(0x232d1d5f3b0)
QModbusReply(0x232d1d604e0)
QModbusReply(0x232d1d60f00)
QModbusReply(0x232d1d630e0)
"TCP socket error (The remote host closed the connection)."
QModbusDevice::UnconnectedState
QObject(0x0)
QObject(0x0)
QObject(0x0)
QObject(0x0)
QObject(0x0)
远程服务器关闭之后,reply的响应函数中访问reply竟然是空值!!!
所以在响应函数中还要判断reply是都为空值,才能继续:
m_reply= m_modbus->sendReadRequest(m_unit[1], m_outputID);if(m_reply && !m_reply->isFinished()){connect(m_reply, &QModbusReply::finished, [this]() {if (!m_reply[0]) {return ;}if(m_reply->error() == QModbusDevice::NoError){m_outputs = m_reply->result().values();}m_modbus->disconnect(SIGNAL(timeoutChanged(int)), 0, 0);delete m_reply;m_reply = nullptr;});}
这样处理后程序终于正常了,但是又出现了另一个问题。
5.方案五(完整解决)
上述方案中使用deleter m_reply竟然也有问题。当本来通信超时的时候(比如传入的错误的通信地址),响应会比较慢。此时服务器断开连接,reply竟然不是nullptr,此时程序在delete reply这句崩了。怀疑此时的reply还在异步处理别的事情。改成reply->deleterLater()之后就没问题了。
还有一个隐藏的问题,m_modbus->disconnect(SIGNAL(timeoutChanged(int)), 0, 0) 这句是为了解决内存增加问题,如果服务器中断导致reply==nullptr,这句话就被跳过了。可以把这句放在函数体最前面,并没有导致问题。
完整解决后如下:
m_reply = m_modbus->sendReadRequest(read, m_485ID);if(m_reply && !m_reply->isFinished()){connect(m_reply, &QModbusReply::finished, [this]() {m_modbus->disconnect(SIGNAL(timeoutChanged(int)), 0, 0);//如果远程服务器关闭,这个reply是0if (!m_reply) {return ;}if(m_reply->error() == QModbusDevice::NoError){QVector<quint16>values = m_reply->result().values();if(m_values != values) {m_values = values;}}//如果超时错误,下面不能直接delete,否则服务中断仍然崩溃m_reply->deleteLater();m_reply = nullptr;});}else {m_modbus->disconnect(SIGNAL(timeoutChanged(int)), 0, 0);m_reply->deleteLater();m_reply = nullptr;}
目前算是彻底解决崩溃问题,后面继续测试。
相关文章:
QModbusTCPClient 服务器断开引起的程序崩溃
最近使用QModbusTCPClient 与一套设备通信,有一个QTimer频繁的通过读取设备寄存器。程序运行良好,但是有个问题:正常进行中设备断电了,整个程序都会崩溃。解决过程如下: 1.失败方案一 在QModbusTCPClient的errorOccu…...
Vue 3 30天精进之旅:Day 11 - 状态管理
在开发复杂的前端应用时,状态管理是一个不可或缺的部分。Vuex是Vue.js官方提供的状态管理库,能够高效地管理应用中的共享状态。它使得各个组件之间的状态共享和维护变得更加简单和清晰。今天,我们将探讨以下几个方面: Vuex概述安…...
npm 和 pip 安装中常见问题总结
安装路径的疑惑:NPM 和 PIP 的安装机制 NPM 安装路径规则: 依赖安装在项目目录下: 当你运行 npm install --save-dev jest,它会在当前目录(例如 F:\)下创建一个 node_modules 文件夹,把 jest 安…...

Flutter开发环境配置
下载 Flutter SDK 下载地址:https://docs.flutter.cn/get-started/install M1/M2芯片选择带arm64字样的Flutter SDK。 解压 cd /Applications unzip ~/Downloads/flutter_macos_arm64_3.27.3-stable.zip执行 /Applications/flutter/bin/flutterManage your Flut…...
Two Divisors ( Educational Codeforces Round 89 (Rated for Div. 2) )
Two Divisors ( Educational Codeforces Round 89 (Rated for Div. 2) ) You are given n n n integers a 1 , a 2 , … , a n a_1, a_2, \dots, a_n a1,a2,…,an. For each a i a_i ai find its two divisors d 1 > 1 d_1 > 1 d1…...

亚博microros小车-原生ubuntu支持系列:17 gmapping
前置依赖 先看下亚博官网的介绍 Gmapping简介 gmapping只适用于单帧二维激光点数小于1440的点,如果单帧激光点数大于1440,那么就会出【[mapping-4] process has died】 这样的问题。 Gmapping是基于滤波SLAM框架的常用开源SLAM算法。 Gmapping基于RBp…...

Java面试题2025-并发编程进阶(线程池和并发容器类)
线程池 一、什么是线程池 为什么要使用线程池 在开发中,为了提升效率的操作,我们需要将一些业务采用多线程的方式去执行。 比如有一个比较大的任务,可以将任务分成几块,分别交给几个线程去执行,最终做一个汇总就可…...
Stable Diffusion 3.5 介绍
Stable Diffusion 3.5 是由 Stability AI 推出的最新一代图像生成模型,是 Stable Diffusion 系列的重要升级版本。以下是关于 Stable Diffusion 3.5 的详细信息: 版本概述 Stable Diffusion 3.5 包含三个主要版本: Stable Diffusion 3.5 L…...
云计算部署模式全面解析
目录 引言公有云私有云混合云三种部署模式的对比选择建议未来趋势结语 1. 引言 随着云计算技术的快速发展,企业在选择云部署模式时面临着多种选择。本文将深入探讨云计算的三种主要部署模式:公有云、私有云和混合云,帮助读者全面了解它们的特点、优势及适用场景。 © iv…...
Vue 与 Electron 结合开发桌面应用
1. 引言 1.1 什么是 Electron? Electron 是一个使用 JavaScript、HTML 和 CSS 构建跨平台桌面应用程序的框架。它结合了 Chromium 渲染引擎和 Node.js 运行时,使得开发者可以使用 Web 技术创建原生桌面应用。1.2 为什么选择 Vue.js 和 Electron? Vue.js 是一个渐进式 JavaSc…...
数据库优化:提升性能的关键策略
1. 引言 在后端开发中,数据库的性能直接影响系统的稳定性和响应速度。随着业务增长,数据库查询变慢、负载过高等问题可能会影响用户体验。 本文将介绍数据库优化的关键策略,包括索引优化、查询优化、分库分表、缓存机制等,并结合…...

使用openAI与Deepseek的感受
今天简单介绍下使用OpenAI和DeepSeek的感觉,有些地方可能存在不准确的地方,望指正: 从2023年的秋冬到现在2025年的1月间,OpenAI和DeepSeek我都用它们来帮我,当然更多的是OpenAI,但整体感受如下:…...

pytorch实现长短期记忆网络 (LSTM)
人工智能例子汇总:AI常见的算法和例子-CSDN博客 LSTM 通过 记忆单元(cell) 和 三个门控机制(遗忘门、输入门、输出门)来控制信息流: 记忆单元(Cell State) 负责存储长期信息&…...
【ubuntu】双系统ubuntu下一键切换到Windows
ubuntu下一键切换到Windows 1.4.1 重启脚本1.4.2 快捷方式1.4.3 移动快捷方式到系统目录 按前文所述文档,开机默认启动ubuntu。Windows切换到Ubuntu直接重启就行了,而Ubuntu切换到Windows稍微有点麻烦。可编辑切换重启到Windows的快捷方式。 1.4.1 重启…...

【PyTorch】6.张量形状操作:在深度学习的 “魔方” 里,玩转张量形状
目录 1. reshape 函数的用法 2. transpose 和 permute 函数的使用 4. squeeze 和 unsqueeze 函数的用法 5. 小节 个人主页:Icomi 专栏地址:PyTorch入门 在深度学习蓬勃发展的当下,PyTorch 是不可或缺的工具。它作为强大的深度学习框架&am…...

大模型GUI系列论文阅读 DAY4续:《Large Language Model Agent for Fake News Detection》
摘要 在当前的数字时代,在线平台上虚假信息的迅速传播对社会福祉、公众信任和民主进程构成了重大挑战,并影响着关键决策和公众舆论。为应对这些挑战,自动化假新闻检测机制的需求日益增长。 预训练的大型语言模型(LLMs࿰…...

论文阅读(九):通过概率图模型建立连锁不平衡模型和进行关联研究:最新进展访问之旅
1.论文链接:Modeling Linkage Disequilibrium and Performing Association Studies through Probabilistic Graphical Models: a Visiting Tour of Recent Advances 摘要: 本章对概率图模型(PGMs)的最新进展进行了深入的回顾&…...
python小知识-typing注解你的程序
python小知识-typing注解你的程序 1. Typing的简介 typing 是 Python 的一个标准库,它提供了类型注解的支持,但并不会强制类型检查。类型注解在 Python 3.5 中引入,并在后续版本中得到了增强和扩展。typing 库允许开发者为变量、函数参数和…...

git基础使用--1--版本控制的基本概念
git基础使用–1–版本控制的基本概念 1.版本控制的需求背景,即为啥需要版本控制 先说啥叫版本,这个就不多说了吧,我们写代码的时候肯定不可能一蹴而就,肯定是今天写一点,明天写一点,对于项目来讲ÿ…...

“新月智能武器系统”CIWS,开启智能武器的新纪元
新月人物传记:人物传记之新月篇-CSDN博客 相关文章链接:星际战争模拟系统:新月的编程之道-CSDN博客 新月智能护甲系统CMIA--未来战场的守护者-CSDN博客 “新月之智”智能战术头盔系统(CITHS)-CSDN博客 目录 智能武…...

C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...

HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...