預防記憶體洩漏規律總結

2021-10-20 19:26:56 字數 2379 閱讀 9578

1. 早發現,早解決

每寫完乙個功能的**,可以是函式、或者類、或者模組都應該進行測試。

如果公司有單元測試工具,那自然最好。如果沒有可以自己寫些測試函式。

這個除了對記憶體,對一般功能測試、函式介面測試等都是應該的。

程式的可除錯性也是考慮乙個程式設計師的功底,個人認為。

2. 有良好的設計

設計是個很大的話題,這裡專門是針對記憶體的建議。

*2.1 養成良好的編碼習慣*

建立和釋放要集中,在乙個類中要配對,如 init---uninit,create---destroy。

釋放的順序應和分配的順序相反。這個說起來容易,做起來難。

*2.2 集中管理*

例如使用記憶體池。記憶體使用物件比較多,或者使用頻繁,例如像我們對檔案的讀寫迴圈一般就需要使用記憶體池。

如果只是小量使用,可能就是物件的初始化,或者定義一些檔名,一般用不上記憶體池,那麼也應該集中放在乙個函式中,例如上面提到的配對函式。

原則不能太分散了,見過有些不規範的程式設計,可以叫做「隨用隨調(記憶體分配)」,這種情況看**費勁,往往很容易出各種記憶體問題。

*2.3 用try catch,捕獲異常*

對所有的new/malloc、delete/free等相關的函式都應該加上,這在一些檢查工具例如pc-lint有要求的。

這裡往往也能捕獲到一些記憶體越界,踩坑經驗總結(一)的案例二。

*2.4 對記憶體的變化加日誌跟蹤*

特別是異常情況,例如判斷輸入的緩衝長度和輸出長度。

*2.5 dll動態庫的特別之處*

我們以提問的方式來說明,一些注意事項。

(1)ddl的庫內部分配的記憶體,是否可以在呼叫者模組中釋放? 即 a庫分配的記憶體可以在b庫釋放嗎?

(2)如果不釋放,除了記憶體洩露外,有沒有其他影響?

答:(1)模組間記憶體使用一**原則:誰分配誰釋放。

(2)當系統退出時,該dll需要5秒的時間來清理資源。也就是說比正常退出延時5秒。

上面的方法適用於開發階段。而真正到了維護階段,重點不一樣了。
1. 了解程式的流程和設計原理

你要解決乙個問題,首先要了解它的來龍去脈。

*1.1 主體流程*

首先要對程式要有個大體認識,理解業務大體流程和模組之間的關係。

盡量拿到框架設計圖和類圖,如果沒有簡單畫一畫。

*1.2 關鍵細節*

資料的流向往往都需要通過快取作為載體,所以抓住關鍵的物件,這些物件一般使用頻率較高,注意記憶體指標的移動,可以畫畫時序圖。

*1.3 盡量重現,找到規律*

找到規律了,我認為就成功一半了。找到規律可以縮小範圍,可以定位到某個功能點或者某個模組,要是某個類就更好了。

*1.4 開源庫的排查*

主要排查啟動和退出的時候記憶體的使用。

我一直認為開源庫的穩定性一般沒有太大問題,因為有很多高手在維護。問題是我們在使用的時候,有時沒有理解他的流程和原理,所以由回到了上面。這裡舉兩個小例子說明。

sip協議庫,還在上一家公司好像是voip的乙個專案,出現了記憶體洩露,後面排查是會話的退出有個釋放函式沒有被呼叫。當時經驗不足,用了c語言的檢測工具,除錯時間還是比較久的。

snmp開源庫,是在這家公司做乙個批量公升級工具,出現了記憶體洩露,當時直接查了下退出的一些函式,乙個個釋放函式試試,除錯幾番就解決了。

開源庫一般會比較複雜點,我記得這兩個庫的釋放函式都不簡單,又都是c語言寫的,指標飛來飛去的,會把你給看暈,文件可能不是你想要的,最重要的是你可能只是使用下,沒想過要深入。但是同樣解決起來也是相對比較容易的。

2.工具

兩種工具,一種是自研的,可以跨平台。一種是windbg的umdb。

最後,複雜問題的記憶體洩露的難點是什麼?

是編寫乙個檢測工具,還是工具的熟練使用?我的回答都不是,工具固然重要。但是有了工具,如何使用,真的都能查得出來?

例如我們的案例裡面,是和

三、四個模組,好像都有關。所以雖然自研的工具應該更好用,但是不可能每個模組的每個類都去改下巨集,工作量極大。但是後面用umdb也沒有找到原因。當然正規的查詢也還是需要,事實上umdb還是提供了很好的線索。

但是最後誰也沒想到是乙個不該使用而使用了的配置項!但是為什麼還是發現了,有個很重要的觀點,全域性觀!

再例如我們上面說的dll庫、開源庫等等,用普通的思維(定勢思維)可能很難理解,但是你站在更高一點,你從外面全域性審視一下,你發現就可以理解了。

在龐大的程式中,程式結構或者系統分析才是重點和難點。當系統較複雜時候,是否需要全部檢查還是檢查某個模組;以及在哪個時候哪個地方進行釋放。

記憶體洩漏問題總結

同事有乙個帶有少量業務邏輯然後更新資料庫某字段的需求 大約900萬資料 執行了幾千條後,發現日誌停住了。使用jvisualvm檢視gc,發現old區和eden區都已經滿了 第一反應是可能存在記憶體洩漏,但是看到系統初始化引數裡面最大堆記憶體大小只有512m,就覺得調大堆記憶體就應該可以了。所以把堆記...

C 記憶體洩漏總結

關於c 全域性變數的釋放問題,一直比較模糊,今天做了乙個測試 一 關於全域性變數的指標型別,程式在退出時,動態建立的物件還存在於記憶體中,導致記憶體洩漏 1 include 2 3 include vld.h 記憶體洩漏檢測工具 4 pragma comment lib,vld.lib 56 usi...

夏季病預防規律

初伏過後,氣溫是一天高過一天,酷暑難耐,如果不注意養身與調攝,是很容易犯病,在這裡,我想和大家談談這個季節發病的特點,以此聊聊中醫藥防治夏季疾病的規律。外感病以 暑熱 病為主 六氣當中,這個季節是暑氣當令,暑氣有何特點?一則具有火熱之性,發病急劇,傳變迅速 二則暑氣通於心,暑病易出現心神症狀 輕則心...