一文搞懂內存泄漏:進程內存段的 “漏洞” 與修復之道

01/13 15:55
2173
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

當進程通過malloc申請虛擬內存后,操作系統(tǒng)不會立即為其分配物理內存,而是在首次訪問時,才觸發(fā)缺頁異常分配內存。對普通進程來說,能看到的是內核提供的虛擬內存,這些虛擬內存還需要通過頁表,由系統(tǒng)映射為物理內存。

為平衡CPU與磁盤間的性能差異,Linux會使用Cache把文件數(shù)據(jù)緩存到內存中。

內存分配

用戶空間內存包括多個不同類型的內存段,比如只讀段、數(shù)據(jù)段、堆、棧以及文件映射段等,下面逐個分析哪些地方可能出現(xiàn)內存泄漏。

只讀段,包括程序的代碼和常量,只讀段不會再去分配新的內存,因此不會產(chǎn)生內存泄漏。

數(shù)據(jù)段,包括全局變量和靜態(tài)變量,這些變量在定義時就已經(jīng)確定了大小,也不會產(chǎn)生內存泄漏。

棧內存由系統(tǒng)自動分配和管理,只會出現(xiàn)爆?;蛘卟葍却媲闆r,超出了局部變量的作用域時,棧內存會被系統(tǒng)自動回收,不會出現(xiàn)內存泄漏情況。

堆內存應用程序自己來分配和管理,如果業(yè)務沒有正確釋放堆內存,就會造成內存泄漏,所以沒有特殊情況,盡量使用智能指針管理對象生命周期。

內存映射段,包括動態(tài)鏈接庫和共享內存,其中共享內存由程序動態(tài)分配和管理。所以如果程序在分配后忘了回收,就會導致內存泄漏。

對于內存泄漏,只能依賴系統(tǒng)OOM機制殺死進程,但是此時已經(jīng)造成了嚴重的性能問題,如系統(tǒng)的緩存頻繁回收等,會導致業(yè)務不可用。

系統(tǒng)命令

top?能觀察系統(tǒng)和進程的內存占用情況,vmstat能觀察內存的變化趨勢。

觀察free列,如果一直在減小,說明系統(tǒng)可用內存在變少??梢酝ㄟ^top或ps來觀察進程的內存使用情況,然后找出內存使用一直增長的進程,最后再通過pmap分析進程地址空間中內存的使用情況。

使用緩沖區(qū)分析工具cachetop分析這些緩存被哪些進程占用;free查看可用內存被哪些進程占用。

cachetop可以分析業(yè)務是否有繞過緩存直接讀取磁盤,導致讀寫速度慢;strace可以查看具體的系統(tǒng)調用:

strace -p $(pgrep)?PID

檢測工具

如果是編碼階段,在上線前檢查代碼中資源獲取的方式,盡量改為智能指針自動管理資源生命周期;禁止系統(tǒng)的swap機制,減少內存和硬盤的交換數(shù)據(jù)導致性能開銷。

如果是調試階段檢查內存泄漏,可以mock掉業(yè)務的malloc和free,在malloc/new時將調用方法、申請地址寫入指定文件新增一條記錄,free時根據(jù)地址刪除該條記錄,在程序運行結束后可以從文件中找到內存泄漏的地方。

bcc中的memleak就是類似思路,利用插樁統(tǒng)計分配的字節(jié)和釋放的字節(jié),兩者進行抵消,而沒有釋放的調用棧就是可能泄露的地方。

其他內存泄漏檢測工具:

AddressSanitizer:速度快,首選;

Valgrind:攔截內存分配和釋放函數(shù),無需修改代碼,但是速度比較慢;

mtrace:通過環(huán)境變量替換malloc和free函數(shù),方便使用。

相關推薦

登錄即可解鎖
  • 海量技術文章
  • 設計資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄