1. 程式人生 > 其它 >Qt串列埠通訊 waitForReadyRead函式與waitForBytesWritten函式導致的記憶體增長問題記錄

Qt串列埠通訊 waitForReadyRead函式與waitForBytesWritten函式導致的記憶體增長問題記錄

https://blog.csdn.net/yzt629/article/details/105777550

這段時間做專案需要有一個進行快速採集資訊的裝置,但是在單獨測試的過程中發現程式的記憶體佔用會一直增長,也就是所謂的記憶體洩露問題。這個問題困擾了我們幾個星期,我嘗試了通過事件迴圈重寫waitfor系列函式來解決這個問題,但是由於執行緒包含問題導致了新的問題。。。今天在Qt的官方論壇上搜索時發現15年就有人發現了這個問題,然後上傳了bug庫並得到了解決,所以特此記錄。

1.問題描述

 通過形如下面的程式碼進行串列埠的讀取或者寫入(高頻率),會導致執行exe的記憶體佔用不斷提升,在一定時間後記憶體洩露到一定程度會導致軟體崩潰。

while (1) 
{
	if (port.waitForReadyRead(10)) 
	{
		port->readAll();
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2.問題原因分析

 因為waitfor系列函式是通過readyRead()訊號與bytesWritten()訊號來實現的,如果產生這兩個訊號過快(就像上面的程式碼,死迴圈執行瘋狂產生訊號),會導致對應到槽函式的事件(訊號到槽的執行是一種事件,我之前寫過,這個事件將會到對應執行緒的訊息佇列中排隊等待執行)一直在訊息佇列中瘋狂阻塞,阻塞的結果就是訊息佇列不斷膨脹,從而記憶體不斷增加,直到佇列到達上限導致程式崩潰。

3.問題解決方案

 知道原理後問題解決就很簡單了,說穿了就是讓執行緒去執行訊息佇列中的事件而不是一直產生,而Qt專門為這種情況制定了一個函式:qApp->processEvents(),這個函式的意思就是讓呼叫此函式的執行緒執行其訊息佇列中的事件,直至沒有事件可以執行為止。可見在死迴圈中加上這個函式之後,相關的記憶體洩露問題將迎刃而解,就像下面這樣:

while (1) 
{
	if (port.waitForReadyRead(10)) 
	{
		qApp->processEvents();
		port->readAll();
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

後記:真的是一個很簡單的問題,但是之前一直沒有考慮這麼多,真的是很慚愧,畢竟自己以後用Qt的機會將會越來越少,現在居然還碰到這麼簡單的問題拖了這麼久才解決,真的是非常愧疚。不僅是自己能力上的愧疚,還有就是對於解決方案搜素的愧疚,一個15年就在論壇上討論並提出bug後解決的問題,居然困擾了自己這麼久,很是慚愧。
此bug討論網址:https://forum.qt.io/topic/59472/qtserialport-and-memory-usage
此bug解決方案:https://bugreports.qt.io/browse/QTBUG-48653