【C++軟件實戰問題排查經驗分享】UI界面卡頓 | CPU占用高 | GDI對象泄漏 | 線程堵塞 系列問題排查總結

目錄

1、UI界面卡頓問題排查

2、軟件CPU占用高問題排查

3、UI界面顯示異常(GDI對象泄漏導致窗口繪制異常)問題排查

4、軟件線程堵塞(包含線程死鎖)問題排查

5、最后


C++軟件異常排查從入門到精通系列教程(核心精品專欄,訂閱量已達5000多個,歡迎訂閱,持續更新...)https://blog.csdn.net/chenlycly/article/details/125529931C/C++實戰專欄(重點專欄,專欄文章已更新500多篇,訂閱量已達3000多個,歡迎訂閱,持續更新中...)https://blog.csdn.net/chenlycly/article/details/140824370C++ 軟件開發從入門到實戰(重點專欄,專欄文章已更新300多篇,歡迎訂閱,持續更新中...)https://blog.csdn.net/chenlycly/category_12695902.htmlVC++常用功能開發匯總(專欄文章列表,歡迎訂閱,持續更新...)https://blog.csdn.net/chenlycly/article/details/124272585C++軟件分析工具從入門到精通案例集錦(專欄文章,持續更新中...)https://blog.csdn.net/chenlycly/article/details/131405795開源組件及數據庫技術(專欄文章,持續更新中...)https://blog.csdn.net/chenlycly/category_12458859.html網絡編程與網絡問題分享(專欄文章,持續更新中...)https://blog.csdn.net/chenlycly/category_2276111.html? ? ? ?我們在開發調試C++軟件的過程中,時常會遇到軟件UI界面卡頓CPU占用高GDI對象泄漏線程堵塞(死鎖)這些常見問題,本文對這些問題的分析與排查方法進行詳細的總結,并給出相關的實戰分析實例,供大家借鑒或參考。

1、UI界面卡頓問題排查

? ? ? ?當UI界面時不時出現卡頓,可能是UI線程執行了不該執行的、比較耗時的操作引起的。我們在項目中遇到過,一個問題場景是在UI線程中向文件寫日志,一個問題場景是在UI線程的代碼中調用了Sleep函數。

? ? ? ?對于寫日志到文件中,會比較耗時,會直接導致UI線程的短暫堵塞。因為寫文件時的文件IO操作,相對與內存讀寫操作會慢很多,一般不能在UI線程中向文件中寫日志,應該把寫日志的操作放到新開的線程中。我們在項目中曾經遇到過這樣的問題,將寫日志的代碼移到新開的線程中。

? ? ? ?對于在UI線程中調用Sleep函數,當UI線程執行到Sleep函數調用時,UI線程會進入短暫的睡眠狀態,UI線程會短暫的掛起不執行,所以會出現UI界面卡頓。我們在項目中遇到的問題場景是這樣的,同事為了實現某個功能,從網上拷貝了一段代碼,將該段代碼直接放置在UI線程中。代碼中設置了定時器,定時執行該段代碼,而這段代碼中調用了Sleep函數:

void CalCPURate()
{// ...Sleep(500);// ...
}

上述代碼運行在UI線程中。當UI線程執行到Sleep函數時,UI線程就會被掛起不執行,從而導致UI界面的堵塞。

? ? ? ?這個UI界面時不時卡頓問題,最初是測試人員發現的,他們反饋這個問題是最近才出現的,前端時間是沒有的。但負責開發當前軟件的同事嘗試查了一下源碼,并沒有找出問題。于是我建議同事用歷史版本比對法,在時間上使用二分法,安裝不同時間點的版本,看看問題是從哪天出現的,引發問題的代碼點應該就在前一天提交的代碼中。最后定位了問題,是從網上拷貝的代碼中調用了Sleep導致的堵塞。

? ? ? ?關于UI界面卡頓,我之前做過詳細的總結,可以查看我的文章:

C++程序卡死、UI界面卡頓問題的原因分析與總結https://blog.csdn.net/chenlycly/article/details/128703097

2、軟件CPU占用高問題排查

? ? ? ?軟件占用CPU高,一般是因為程序中在不停歇的執行代碼,一般是代碼發生死循環導致的。代碼發生死循環,可能是以下幾個原因導致的:

1)在for或while循環中循環條件有問題,導致循環一直結束不了。比如因為手誤,將循環條件中的i<=5,錯誤寫成了i=5賦值操作:

for ( int i = 0; i = nChannelNum - 1; i++)
{// ......
}

導致一直跳不出循環。再比如循環條件中引用了一個變量,而這個變量在某種場景下出現了異常大的值:(變量nChannelNum的值是一個異常大的值)

for ( int i = 0; i < nChannelNum; i++)
{// ......
}

導致代碼一直在不停的循環。

2)窗口消息引發的死循環。這個在項目中遇到過,在一個窗口消息A的消息響應函數中調用某個函數或者某段代碼,這段代碼中又產生了窗口消息B,然后窗口消息B的響應函數中又觸發了窗口消息A的產生,這樣就產生了窗口消息引發的代碼死循環調用,引發死循環。

3)和平臺服務器業務交互消息引發的死循環。這個在項目中也遇到過,客戶端調用了A接口與服務器交互,然后服務器給出了回應消息,然后客戶端在處理該回應消息的響應函數中又調用了A接口,這樣就形成了循環閉環,從而產生了由業務消息引發的死循環。

? ? ? ?如果軟件占用的CPU較高,可能會導致當前電腦占用的總CPU比較高,會導致電腦系統出現卡頓或者明顯的卡頓。可以通過查看Windows任務管理器查看軟件的CPU占用比例和整個電腦的CPU占用比例。

? ? ? 對于軟件CPU占用高的排查,可以借助Process Explorer、Windbg等工具進行分析。可以用Process Explorer中查看軟件進程中所有線程的CPU占用情況,找到占用CPU最高的線程:

雙擊查看該線程的函數調用堆棧:

通過調用堆棧分析占用CPU高的原因。

? ? ? ?Process Explorer中查看的線程函數調用堆棧可能不準,可以將Windbg附加到軟件進程上使用~*kn命令將所有線程的函數調用堆棧打印出來:

然后利用Process Explorer中現實的線程id,到Windbg中找到對應的線程即可。必要時,可以在Windbg中設置斷點進行動態調試,看看具體是哪個函數中發生了死循環。

? ? ? ? 關于高CPU占用的實戰分析案例,我寫過多篇文章,可以查看:
使用Process Explorer/Process Hacker和Windbg高效排查C++程序高CPU占用問題https://blog.csdn.net/chenlycly/article/details/140731953使用Process Explorer和Clumsy工具定位軟件高CPU占用問題https://blog.csdn.net/chenlycly/article/details/130038272


? ? ? ?在這里,給大家重點推薦一下我的幾個熱門暢銷專欄,歡迎訂閱:(博客主頁還有其他專欄,可以去查看)

專欄1:該精品技術專欄的訂閱量已達到50000多個,專欄中包含大量項目實戰分析案例,有很強的實戰參考價值,廣受好評!專欄文章持續更新中,已經更新到200篇以上!歡迎訂閱!)

C++軟件調試與異常排查從入門到精通系列文章匯總https://blog.csdn.net/chenlycly/article/details/125529931

本專欄根據多年C++軟件異常排查的項目實踐,系統地總結了引發C++軟件異常的常見原因以及排查C++軟件異常的常用思路與方法,詳細講述了C++軟件的調試方法與手段,以圖文并茂的方式給出具體的項目問題實戰分析實例(很有實戰參考價值),帶領大家逐步掌握C++軟件調試與異常排查的相關技術,適合基礎進階和想做技術提升的相關C++開發人員!

考察一個開發人員的水平,一是看其編碼及設計能力,二是要看其軟件調試能力!所以軟件調試能力(排查軟件異常的能力)很重要,必須重視起來!能解決一般人解決不了的問題,既能提升個人能力及價值,也能體現對團隊及公司的貢獻!

專欄中的文章都是通過項目實戰總結出來的,包含大量項目問題實戰分析案例,有很強的實戰參考價值!專欄文章還在持續更新中,預計文章篇數能更新到200篇以上!

專欄2:(本專欄涵蓋了C++多方面的內容,是當前重點打造的專欄,訂閱量已達30000多個,專欄文章已經更新到500多篇,持續更新中...)

C/C++實戰進階(專欄文章,持續更新中...)https://blog.csdn.net/chenlycly/category_11931267.html

以多年的開發實戰為基礎,總結并講解一些的C/C++基礎與項目實戰進階內容,以圖文并茂的方式對相關知識點進行詳細地展開與闡述!專欄涉及了C/C++領域多個方面的內容,包括C++基礎及編程要點(模版泛型編程、STL容器及算法函數的使用等)、數據結構與算法、C++11及以上新特性(不僅看開源代碼會用到,日常編碼中也會用到部分新特性,面試時也會涉及到)、常用C++開源庫的介紹與使用、代碼分享(調用系統API、使用開源庫)、常用編程技術(動態庫、多線程、多進程、數據庫及網絡編程等)、軟件UI編程(Win32/duilib/QT/MFC)、C++軟件調試技術(排查軟件異常的手段與方法、分析C++軟件異常的基礎知識、常用軟件分析工具使用、實戰問題分析案例等)、設計模式、網絡基礎知識與網絡問題分析進階內容等。

專欄3:??

C++常用軟件分析工具從入門到精通案例集錦匯總(專欄文章,持續更新中...)https://blog.csdn.net/chenlycly/article/details/131405795

常用的C++軟件輔助分析工具有SPY++、PE工具、Dependency Walker、GDIView、Process Explorer、Process Monitor、API Monitor、Clumsy、Windbg、IDA Pro等,本專欄詳細介紹如何使用這些工具去巧妙地分析和解決日常工作中遇到的問題,很有實戰參考價值!

專欄4:???

VC++常用功能開發匯總(專欄文章,持續更新中...)https://blog.csdn.net/chenlycly/article/details/124272585

將10多年C++開發實踐中常用的功能,以高質量的代碼展現出來。這些常用的高質量規范代碼,可以直接拿到項目中使用,能有效地解決軟件開發過程中遇到的問題。

專欄5:?

C++ 軟件開發從入門到精通(專欄文章,持續更新中...)https://blog.csdn.net/chenlycly/category_12695902.html

根據多年C++軟件開發實踐,詳細地總結了C/C++軟件開發相關技術實現細節,分享了大量的實戰案例,很有實戰參考價值。


3、UI界面顯示異常(GDI對象泄漏導致窗口繪制異常)問題排查

? ? ? ?UI界面顯示不正常,窗口繪制異常,可能是軟件進程占用的GDI對象總數異常高導致的。這類問題我們在項目中多次遇到了,一般是使用GDI對象繪圖時有GDI對象泄漏導致的。GDI對象泄漏是指GDI對象使用完成后,沒有調用Delete或者Release相關接口將GDI對象釋放,從而產生了泄漏。

? ? ? ?對于GDI對象泄漏問題,們可以借助GDIView工具來輔助排查。當UI界面顯示異常時,可以打開系統的任務管理器:

如果我們軟件進程的GDI對象異常的高,接近進程10000個上限,那肯定是GDI對象引起的。當進程的GDI對象達到或接近10000個上限時,程序中調用的GDI繪圖API函數可能會失敗,導致界面繪制失敗,從而引發界面顯示異常。

? ? ? ?可以使用GDIView查看到底是哪個GDI對象個數異常的高

這樣排查起來會比較有針對性。但光知道發生泄漏的GDI對象類型,可能還是較難定位問題。可能軟件從上到下有很多模塊,不確定GDI對象泄漏發生在哪個模塊。此外,可能發生泄漏的代碼平時很難被頻繁的執行,只是在某種特定的場景下才會被頻繁地執行,這種情況比較具有隱蔽性,或者是這個問題隱藏的比較深。這兩類比較有代表性的問題場景,我們在項目中都遇到過。

? ? ? ?所以,除了使用GDIView工具之外,可能還需要結合歷史版本比對法(下面給出的案例會講到歷史版本比對法),找到發生泄漏的時間點,到svn或git上查看前一天提交的代碼或者底層發布過來的模塊,可能就能找到引發問題的代碼點了。

? ? ? ?之前寫過多篇排查GDI對象泄漏的案例,可以去查看這些文章:
使用GDIView工具排查GDI對象泄漏問題(實戰分析案例)https://blog.csdn.net/chenlycly/article/details/125399896使用GDIView工具排查GDI對象泄漏案例的若干細節總結(歷史版本比對法)https://blog.csdn.net/chenlycly/article/details/141526436使用GDIView工具排查GDI對象泄漏導致C++程序UI界面繪制異常的問題https://blog.csdn.net/chenlycly/article/details/140731065可以到GDIView等工具官網上或者微軟MSDN上查看文檔化說明去解決問題https://blog.csdn.net/chenlycly/article/details/139565010使用GDI對象繪制UI時需要注意的若干細節問題總結https://blog.csdn.net/chenlycly/article/details/144233359

4、軟件線程堵塞(包含線程死鎖)問題排查

? ? ? ?線程中調用了某個接口,該接口一直沒返回,這樣就會導致調用該接口的線程發生堵塞。如果UI線程堵塞了,就會導致UI界面卡死不可操作(無法點擊);如果業務線程堵塞了,則會導致業務出現異常(但UI界面不會卡死,UI界面可以正常點擊)。導致接口堵塞不返回,可能有以下幾個原因

1)多線程死鎖:接口中申請了鎖,但鎖被其他線程占用,導致一直拿不到鎖,接口不返回,即產生了多線程死鎖。
2)安全軟件攔截:接口中執行了寫注冊表等操作,PC上安裝的安全軟件可能認為是不安全的,直接將操作攔截了,可能會導致接口不返回,這個場景我們在項目中遇到過。
3)接口中發生了死循環:接口中有for或while循環,因為某種原因到之后導致死循環,導致接口一直不返回。

? ? ? ?如果堵塞的是UI線程,則UI界面不可操作,UI線程卡死了,一般是調用底層的接口沒返回導致的,這種堵塞能被用戶第一時間察覺。如果堵塞的是業務線程,就要根據UI界面表現現象以及打印日志去判斷。比如加入會議后,看不到會議中的視頻圖像,可能是底層音視頻處理模塊中繪制視頻的業務線程出現了堵塞,沒法繪制視頻畫面。

? ? ? ?對于死循環引發的線程堵塞,會有個典型的特征,會導致高CPU占用,高CPU的排查方法我們上面已經說過了。

? ? ? ?對于安全軟件攔截引發的線程堵塞,可以將Windbg附加到出問題的進程上,查看所有線程的調用堆棧,找到目標線程堆棧中調用的函數,看看是否執行了寫注冊表等安全軟件比較敏感的操作,找出可能的原因。必要時可以借助日志去輔助分析。之前就遇到過這類案例,我寫了專題文章,可以去查看文章:
使用Windbg排查C++軟件安裝包安裝時被安全防護軟件攔截導致安裝線程堵塞卡住的問題https://blog.csdn.net/chenlycly/article/details/143670974

文章中有一點需要注意一下,雖然將騰訊電腦管家軟件退出了,但其實時防護模塊還在后臺運行,還是會持續攔截,除非將騰訊電腦管家卸載掉。

? ? ? ?對于多線程死鎖,也是將Windbg附加到出問題的進程上,查看所有線程的函數調用堆棧,看看哪些線程調用了WaitForSingleObject等等待函數,結合這些線程堆棧中調用的函數,確定這些線程和哪些業務有關。必要時也要結合日志去排查并最終定位問題。之前寫過使用Windbg排查多線程死鎖的實戰案例,可以去查看我的文章:
使用Windbg分析多線程臨界區死鎖問題分享https://blog.csdn.net/chenlycly/article/details/128532743

5、最后

? ? ? 上述內容均是從項目中遇到的實戰問題總結歸納出來的,很有實戰參考價值,希望能幫到大家。

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

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

相關文章

管理雜談——采石磯大捷的傳奇與啟示

南宋抗金史上&#xff0c;岳飛與岳家軍的鐵血傳奇家喻戶曉&#xff0c;但另一位力挽狂瀾的“文官戰神”卻常被忽視——他從未掌兵&#xff0c;卻在南宋存亡之際整合潰軍&#xff0c;以少勝多&#xff0c;締造采石磯大捷。此人正是虞允文。一介書生何以扭轉乾坤&#xff1f;他的…

動態規劃-零錢兌換

332.零錢兌換 給你一個整數數組 coins &#xff0c;表示不同面額的硬幣&#xff1b;以及一個整數 amount &#xff0c;表示總金額。計算并返回可以湊成總金額所需的 最少的硬幣個數 。如果沒有任何一種硬幣組合能組成總金額&#xff0c;返回 -1 。你可以認為每種硬幣的數量是無…

SpringAI+DeepSeek大模型應用開發——4 對話機器人

目錄??????? ??????????????項目初始化 pom文件 配置模型 ChatClient 同步調用 流式調用 日志功能 對接前端 解決跨域 會話記憶功能 ChatMemory 添加會話記憶功能 會話歷史 管理會話id 保存會話id 查詢會話歷史 完善會話記憶 定義可序列…

Java 關鍵字

本章列出了Java 語言的所有關鍵字和“類關鍵字的單詞”。 “受限關鍵字”是指&#xff0c;它們旨在模塊聲明中是關鍵字&#xff0c;在其他情況下則是標識符。 “受限標識符”是指&#xff0c;除非用在某些特定位置&#xff0c;否則他們只是標識符。例如&#xff0c;var一般都…

AI重塑網絡安全:機遇與威脅并存的“雙刃劍”時代

一、引言 人工智能&#xff08;AI&#xff09;技術的迅猛發展&#xff0c;正在深刻改變網絡安全行業的格局。從ChatGPT生成釣魚郵件到AI驅動的漏洞挖掘&#xff0c;從零信任架構的普及到安全大模型的實戰應用&#xff0c;AI既是攻擊者的“新武器”&#xff0c;也是防御者的“新…

網絡原理——UDP

1、 與TCP的關鍵區別 特性UDPTCP連接方式無連接面向連接可靠性不可靠可靠數據順序不保證順序保證順序傳輸速度更快相對較慢頭部開銷8字節20-60字節流量控制無有擁塞控制無有適用場景實時應用、廣播/多播可靠性要求高的應用 2、UDP 報文結構 報文結構大致可以分為首部和載荷&a…

STM32——新建工程并使用寄存器以及庫函數進行點燈

本文是根據江協科技提供的教學視頻所寫&#xff0c;旨在便于日后復習&#xff0c;同時供學習嵌入式的朋友們參考&#xff0c;文中涉及到的所有資料也均來源于江協科技&#xff08;資料下載&#xff09;。 新建工程并使用寄存器以及庫函數進行點燈操作 新建工程步驟1.建立工程2.…

Unocss 類名基操, tailwindcss 類名

這里只列出 unocss 的可實現類名&#xff0c;tailwindcss 可以拿去試試用 1. 父元素移入&#xff0c;子元素改樣式 <!-- 必須是 group 類名 --> <div class"group"><div class"group-hover:color-red">Text</div> </div>2…

深度學習入門(一)

一、簡介 深度學習是機器學習領域新興且關鍵的研究方向。機器學習重點在于讓計算機從數據中挖掘規律以預測未知&#xff0c;而深度學習借助構建多層神經網絡&#xff0c;自動學習數據的復雜特征&#xff0c;從而實現更精準的模式識別&#xff0c;在圖像、語音等眾多領域廣泛應…

element-plus中,Steps 步驟條組件的使用

目錄 一.基本使用 1.代碼 2.效果展示 3.代碼解讀 二.案例&#xff1a;修改用戶的密碼 1.期望效果 2.代碼 3.展示效果 結語 一.基本使用 1.代碼 從官網復制如下代碼&#xff1a; <template><div><el-stepsstyle"max-width: 600px":space&quo…

jax 備忘錄

https://zhuanlan.zhihu.com/p/532504225 https://docs.jax.dev/en/latest/index.html

NLTK 基礎入門:用 Python 解鎖自然語言處理

自然語言處理&#xff08;NLP&#xff09;是人工智能領域的重要分支&#xff0c;它讓計算機能夠理解、處理和生成人類語言。而 NLTK&#xff08;Natural Language Toolkit&#xff09; 作為 Python 生態中最經典的 NLP 庫之一&#xff0c;提供了豐富的工具和資源&#xff0c;是…

ElementUI中checkbox v-model綁定值為布爾、字符串或數字類型

這篇博客介紹了在Vue.js中使用El-Checkbox組件時&#xff0c;如何設置和處理v-model的布爾值和類型轉換。通過示例代碼展示了如何設置true-label和false-label屬性來改變選中狀態的值&#xff0c;適用于需要特定類型&#xff08;如字符串或整數&#xff09;的場景。v-model不能…

JBoss 項目修復筆記:繞開 iframe 安全問題,JSF 與 Angular 最小代價共存方案

JBoss 項目修復筆記&#xff1a;繞開 iframe 安全問題&#xff0c;JSF 與 Angular 最小代價共存方案 本篇筆記銜接的內容為&#xff1a;JBoss WildFly 本地開發環境完全指南&#xff0c;里面簡單的描述了一下怎么配置 docker&#xff0c;在本地啟動一個可以運行的 JBoss 和 W…

Linux文件時間戳詳解:Access、Modify、Change時間的區別與作用

在 Linux 系統中&#xff0c;文件的這三個時間戳&#xff08;Access、Modify、Change&#xff09;分別表示不同的文件狀態變更時間&#xff0c;具體含義如下&#xff1a; 1. Access Time (Access) 含義&#xff1a;文件最后一次被訪問的時間&#xff08;讀取內容或執行&#xf…

SpringBoot項目打包為window安裝包

SpringBoot項目打包為window安裝包 通過jpackage及maven插件的方式將springboot項目打包為exe或msi pom.xml 添加插件 <plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><version>3.1.0</vers…

pip永久換鏡像地址

要將 pip 永久設置為阿里云鏡像源&#xff0c;可以通過修改 pip 的全局配置文件來實現。以下是具體步驟&#xff1a; 步驟 1&#xff1a;創建或修改 pip 配置文件 根據你的操作系統&#xff0c;配置文件的路徑略有不同&#xff1a; Linux/macOS 配置文件路徑&#xff1a;~/.…

PI0 Openpi 部署(僅測試虛擬環境)

https://github.com/Physical-Intelligence/openpi/tree/main 我使用4070tisuper, 14900k,完全使用官方默認設置&#xff0c;沒有出現其他問題。 目前只對examples/aloha_sim進行測試&#xff0c;使用docker進行部署, 默認使用pi0_aloha_sim模型(但是文檔上沒找到對應的&…

XAttention

XAttention: Block Sparse Attention with Antidiagonal Scoring 革新Transformer推理的高效注意力機制資源?? ??論文鏈接??&#xff1a;XAttention: Block Sparse Attention with Antidiagonal Scoring ??代碼開源??&#xff1a;GitHub倉庫 XAttention是韓松團隊提…

前端中的浮動、定位與布局

在前端開發中&#xff0c;布局是構建網頁結構的基礎。而浮動&#xff08;float&#xff09;、定位&#xff08;position&#xff09;以及各種布局方法則是實現網頁布局的關鍵工具。 一、浮動&#xff08;Float&#xff09; 浮動是CSS中用于控制元素在頁面中排列方式的一種屬性…