linux程式之記憶體洩漏分析

wuruixn發表於2020-04-07
目的:總結linux程式記憶體洩漏導致crash的分析方法及解決過程

問題背景:插入usb裝置並配置啟動dlna功能,測試較長一段時間後會導致cpu和記憶體佔用率很高以致開發板crash,有ps下的程式狀態截圖和crash日誌

關鍵節點:
1.問題crash復現
2.在陌生的原始碼中尋找突破口
3.分析日誌
4.分析主程式及子程式程式碼

分析過程:

節點1——
      按照問題描述進行多次反覆測試,問題並沒有復現。觀察提供的程式狀態截圖,按照截圖中的狀態啟動對應程式(包括voice相關),儘量模擬同樣的環境,繼續測試,問題依然沒有復現。開始懷疑跟usb裝置中的檔案系統、檔案內容(包括圖片格式型別,視訊型別、音訊型別)有關,於是在行動硬碟對應目錄下copy大量的圖片視訊音訊檔案(達到60G左右,上十萬個檔案),測試1個小時左右出現crash,提示voice程式out of memory錯誤。

節點2——
      原始碼檔案那麼多怎麼找突破口,一般是從主程式入手。由於該功能啟動時會用到一個重要引數,即對應的目錄路徑path,開始研究程式如何使用該引數,發現一個重要子程式scan,會迭代掃描path路徑下所有的目錄和檔案並寫入資料庫db檔案,檔案越多掃描程式持續時間越長(可超過1個小時),top觀察記憶體和cpu使用率佔比很高,一段時間後即crash,由於記憶體耗盡導致voice需要大量申請記憶體失敗最終crash。開始懷疑是迭代掃描導致大量記憶體未及時釋放所致。

節點3——
      觀察日誌程式碼發現程式會將日誌儲存在usb裝置path目錄下,於是仔細研究日誌發現,每次都能正常掃描整個目錄,且掃描結束後在做inotify過程中將crash,於是推斷掃描程式沒有洩漏問題,但其依然會耗掉大量記憶體。研究掃描程式之後的程式碼,又發現另一子程式inotify,主要實現媒體檔案的同步操作,該程式會將掃描結果(上萬條媒體記錄)存入連結串列觀測點進行觀測。於是將掃描結束後的inotify相關程式碼註釋掉繼續除錯,發現不再crash。嘗試將inotify記錄數減半,測試也不會crash,但是在播放器中隨意點選播放會出現卡死現象,似乎還是沒有解決根本問題。

節點4——
      回到主程式整體分析,無論前面如何除錯,記憶體總是消耗很大沒有變好趨勢,到底在什麼地方會消耗很大記憶體呢?於是在主程式中去掉兩個子程式,果然記憶體消耗很小。根據前面的除錯,scan程式中沒有記憶體洩漏,scan程式和inotify程式均採用pthread_create方式建立,scan掃描結束後程式也會結束,inotify程式則一直生存。上網查詢發現pthread_create方式使用不當會導致大量記憶體洩漏,預設會消耗2-8M左右記憶體(可調整),根據網上眾多的解決方法調整不起效果,不知緣何。於是想到可不可以將scan和inotify整合到一個程式中,或者採用fork方式來取代pthread_create方式調整scan程式,採用後一種方式調整測試,功能正常,不會crash和卡死現象,效果有改觀,記憶體佔用比降低明顯,掃描結束後趨於穩定。


相關文章