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;}

目前算是徹底解決崩潰問題,后面繼續測試。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/67281.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/67281.shtml
英文地址,請注明出處:http://en.pswp.cn/web/67281.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vue3底層原理和性能優化

Vue 3 在底層原理和性能優化方面做了許多改進&#xff0c;以下是一些主要的優化點和原理&#xff1a; 1. 虛擬 DOM 的改進 靜態樹提升&#xff1a;Vue 3 能夠檢測到靜態組件&#xff08;即不依賴響應式數據的組件&#xff09;并將其提升到渲染函數之外&#xff0c;從而減少不…

開發環境搭建-3:配置 JavaScript 開發環境 (fnm+ nodejs + pnpm + nrm)

在 WSL 環境中配置&#xff1a;WSL2 (2.3.26.0) Oracle Linux 8.7 官方鏡像 node 官網&#xff1a;https://nodejs.org/zh-cn/download 點擊【下載】&#xff0c;選擇想要的 node 版本、操作系統、node 版本管理器、npm包管理器 根據下面代碼提示依次執行對應代碼即可 基本概…

npm:升級自身時報錯:EBADENGINE

具體報錯信息如下&#xff1a; 1.原因分析 npm和當前的node版本不兼容。 // 當前實際版本: Actual: {"npm":"10.2.4","node":"v20.11.0"}可以通過官網文檔查看與自己 node 版本 兼容的是哪一版本的npm&#xff0c;相對應進行更新即可…

WPS數據分析000005

目錄 一、數據錄入技巧 二、一維表 三、填充柄 向下自動填充 自動填充選項 日期填充 星期自定義 自定義序列 1-10000序列 四、智能填充 五、數據有效性 出錯警告 輸入信息 下拉列表 六、記錄單 七、導入數據 ?編輯 八、查找錄入 會員功能 Xlookup函數 VL…

【ProxyBroker】用Python打破網絡限制的利器

ProxyBroker 1. 什么是ProxyBroker2. ProxyBroker的功能3. ProxyBroker的優勢4. ProxyBroker的使用方法5. ProxyBroker的應用場景6.結語項目地址&#xff1a; 1. 什么是ProxyBroker ProxyBroker是一個開源工具&#xff0c;它可以異步地從多個來源找到公共代理&#xff0c;并同…

翼星求生服務器搭建【Icarus Dedicated Server For Linux】

一、前言 本次搭建的服務器為Steam平臺一款名為Icarus的沙盒、生存、建造游戲,由于官方只提供了Windows版本服務器導致很多熱愛Linux的小伙伴無法釋懷,眾所周知Linux才是專業服務器的唯一準則。雖然Github上已經有大佬制作了容器版本但是容終究不夠完美,畢竟容器無法與原生L…

機器學習-線性回歸(參數估計之經驗風險最小化)

給定一組包含 &#x1d441; 個訓練樣本的訓練集 我們希望能夠 學習一個最優的線性回歸的模型參數 &#x1d498; 現在我們來介紹線性回歸的一種模型參數估計方法&#xff1a;經驗風險最小化。 我們前面說過&#xff0c;對于標簽 &#x1d466; 和模型輸出都為連續的實數值&…

前部分知識復習02

一、物體的屏幕UV坐標 float2 ScreenUV i.pos.xy / _ScreenParams.xy; 二、抓取屏幕圖像 GrabPass{" _A "} //_A為貼圖圖像名稱 之后需在Pass中聲明該貼圖才能在Pass中引用此貼圖 三、屏幕抓取并制作熱效應代碼 Shader"unity/HeatDistort 07" {Pr…

YOLOv8:目標檢測與實時應用的前沿探索

隨著深度學習和計算機視覺技術的迅速發展&#xff0c;目標檢測&#xff08;Object Detection&#xff09;一直是研究熱點。YOLO&#xff08;You Only Look Once&#xff09;系列模型作為業界廣受關注的目標檢測框架&#xff0c;憑借其高效、實時的特點&#xff0c;一直迭代更新…

【MQ】探索 Kafka

高性能 消息的順序性、順序寫磁盤 零拷貝 RocketMQ內部主要是使用基于mmap實現的零拷貝&#xff0c;用來讀寫文件 減少cpu的拷貝次數和上下文切換次數&#xff0c;實現文件的高效讀寫操作 Kafka 零拷貝 Kafka 使用到了 mmap 和 sendfile 的方式來實現零拷貝。分別對應 Jav…

VMware 和本機(Win10)安裝共享文件

1. 安裝VM-tools, sudo apt-get install open-vm-tools-desktop -y 2. VMware->設置-> 選項中啟動共享文件夾. 3. 本機設置共享文件夾(文件目錄為data)&#xff0c;右鍵屬性設置: VMware&#xff0c; Other Locations->Computer->mnt->data 即可。 ps: 還有個…

2025美賽MCM數學建模A題:《石頭臺階的“記憶”:如何用數學揭開歷史的足跡》(全網最全思路+模型)

?個人主頁歡迎您的訪問 ?期待您的三連 ? 《石頭臺階的“記憶”&#xff1a;如何用數學揭開歷史的足跡》 目錄 《石頭臺階的“記憶”&#xff1a;如何用數學揭開歷史的足跡》 ?摘要? ?引言? 1. 引言的結構 2. 撰寫步驟 &#xff08;1&#xff09;研究背景 &#…

SpringBoot-Vue整合百度地圖

文章目錄 一、Spring Boot整合百度地圖的步驟1. 申請百度地圖的AK值2. 創建實體類3. 創建Controller層4. 前端集成百度地圖4.1 在Vue項目中安裝百度地圖Vue組件庫4.2 在Vue項目中引入百度地圖API4.3 創建地圖組件 二、實現功能說明1. 前端部分&#xff1a;2. 后端部分&#xff…

Baklib如何優化企業知識管理實現全面數字化升級與協同創新

內容概要 Baklib 作為企業知識管理的重要工具&#xff0c;提供了一個集成化的知識中臺&#xff0c;幫助企業在數字化轉型過程中更高效地管理和利用其知識資產。在現代企業中&#xff0c;知識的管理和應用顯得尤為重要&#xff0c;因為優秀的知識管理能夠直接影響到組織的決策效…

機器學習day4

自定義數據集 使用pytorch框架實現邏輯回歸并保存模型&#xff0c;然后保存模型后再加載模型進行預測 import numpy as np import torch import torch.nn as nn import torch.optim as optimizer import matplotlib.pyplot as pltclass1_points np.array([[2.1, 1.8],[1.9, 2…

天道無極:論文明興衰中的規律自覺與文化覺醒

宇宙洪荒,星河輪轉,人類文明在浩渺時空中不過滄海一粟。當我們剖開青銅器上的饕餮紋,凝視量子計算機的硅基瞳孔,會發現所有文明興衰的背后都躍動著同一組密碼——對規律的認知與駕馭程度,構成了文明存續的底層邏輯。從兩河流域的楔形文字到華爾街的電子屏幕,從雅典學院的…

Linux解決輸入法卡死問題

說明&#xff1a;在Ubuntu系統中&#xff0c;如果您需要重啟輸入法服務&#xff08;比如fcitx或ibus&#xff09;&#xff0c;您可以按照以下步驟操作。這些步驟適用于大多數基于Ubuntu的發行版&#xff0c;例如Ubuntu、Linux Mint等。 一、重啟Fcitx輸入法服務 1、使用Ctrl …

區間選點(貪心)

給定 NN 個閉區間 [ai,bi][ai,bi]&#xff0c;請你在數軸上選擇盡量少的點&#xff0c;使得每個區間內至少包含一個選出的點。 輸出選擇的點的最小數量。 位于區間端點上的點也算作區間內。 輸入格式 第一行包含整數 NN&#xff0c;表示區間數。 接下來 NN 行&#xff0c;…

WPF基礎 | WPF 常用控件實戰:Button、TextBox 等的基礎應用

WPF基礎 | WPF 常用控件實戰&#xff1a;Button、TextBox 等的基礎應用 一、前言二、Button 控件基礎2.1 Button 的基本定義與顯示2.2 按鈕樣式設置2.3 按鈕大小與布局 三、Button 的交互功能3.1 點擊事件處理3.2 鼠標懸停與離開效果3.3 按鈕禁用與啟用 四、TextBox 控件基礎4.…

【huawei】云計算的備份和容災

目錄 1 備份和容災 2 災備的作用&#xff1f; ① 備份的作用 ② 容災的作用 3 災備的衡量指標 ① 數據恢復時間點&#xff08;RPO&#xff0c;Recoyery Point Objective&#xff09; ② 應用恢復時間&#xff08;RTO&#xff0c;Recoyery Time Objective&#xff09; 4…