1. 程式人生 > >【厚積薄發系列】C++專案總結7—實際專案中記憶體洩漏問題排查及常見情況總結

【厚積薄發系列】C++專案總結7—實際專案中記憶體洩漏問題排查及常見情況總結

需求背景:

C/C++專案中,有時候最頭痛不是業務需求實現問題而是隨著專案的日益龐大過程中記憶體洩漏帶來的問題。記憶體洩漏不僅會導致程式記憶體不夠導致程式崩潰,還會導致記憶體碎片,更嚴重還會引起系統莫名其妙的崩潰和閃退。所以在專案中解決記憶體洩漏問題勢在必行。

解決思路:

分兩種情況

第一種情況專案是新啟動的程式碼量也很少,這時候可以從源頭來避免記憶體洩漏問題,可以考慮引入智慧指標自動化管理記憶體釋放問題,也可以引入Tcmalloc記憶體分配工具減少記憶體碎片問題。(第一種後續文章詳說)

第二種情況專案已經開放一段時間了,已經進入中後期。此時的專案可能由於前期為了早點上線加班加點的實現新功能,會留下很多技術債,C/C++專案中比較頭痛的就是記憶體洩漏問題。

系統記憶體佈局分為堆區、棧區、全域性資料庫、常量區、程式碼區。工作中常常說的記憶體洩漏問題就是指的堆區的記憶體洩漏,是指程式設計師自己通過malloc、new申請後沒有呼叫free、delete導致洩漏的記憶體。

具體實現:

1、VLD記憶體洩漏分析工具引入(可以到網上下載),我這邊有做成安裝包形式的直接跟VS掛鉤,安裝後在vs直接包含標頭檔案就可以用(針對所有vs專案),有需要的可以留言。

a、VLD工具包含三個部分include目錄下有vld.h、vld_def.h;lib目錄下有vld.lib,exe對應的bin目錄下有vld_x8.dll和dbghelp.dll(這是32位的也有對應一套64位版本的)可以手動在特定專案目錄中配置,就像使用第三方庫那樣配置使用即可。

b、在需要檢查記憶體洩漏的模組函式入口檔案包含vld.h標頭檔案即可。

c、配置如果測試程式碼和結果如下







常見記憶體洩漏問題及避免方法總結:

1、malloc和free,new和delete沒有配對使用。常見情況呼叫的函式申請記憶體返回出去後,外部需要注意記憶體的釋放。

2、釋放物件陣列時,沒有加[]。

3、缺少拷貝建構函式,可能會導致堆區的崩潰和記憶體洩漏。如果一個類裡面有指標成員變數時,需要顯示的寫拷貝建構函式和過載賦值運算子。如果一個C++類沒有定義拷貝建構函式,難麼編譯器會呼叫預設的拷貝建構函式來複制資料成員,如果類中右動態分配的記憶體空間的指標時,會導致兩個物件指向統一記憶體空間,最後呼叫解構函式的時候會導致兩次釋放問題從而導致崩潰。同理兩個物件都有動態分配的記憶體空間時候如果用=賦值的時候,會導致另一個物件指向的記憶體空間洩漏。

4、沒有將基類的解構函式定義為虛擬函式。如果類成員變數中涉及到動態申請記憶體,且存在派生關係則需要將基類解構函式定義為虛擬函式。

5、指標容器,如std::vector<CTest*>,在clear容器或者刪除元素的時候需要手動釋放器元素記憶體。

6、指標賦值導致記憶體洩漏,如果原指標有值的話需要先把原有的記憶體釋放。

7、掃尾函式的呼叫,如一些公共模組第三方庫初始化和關閉相關介面的配對使用。

8、異常分支或者break、return語句導致的記憶體洩漏問題,正常流程有記憶體釋放,如果有異常是否做到了記憶體釋放。

9、單例模式生命週期問題。

10、執行緒的安全退出,防止執行緒異常中斷導致的記憶體洩漏問題。