linux 内存泄漏 定位,一种内存泄露检查和定位的方法
一個系統后臺服務進程,可能包括多個線程,在生成環境下要求系統程序能夠穩定長時間穩定運行而不宕機。其中一個基本的前提就是需要保證系統程序不存在內存泄露。那么,該如何判讀系統程序是否存在內存泄露呢?如果存在,又該如何檢測呢?
0.判讀系統程序是否存在內存泄露
對于頻繁快速申請內存的應用,可以允許下面的命令:
top
-p `pidof YourProgrogram`
如果看到系統內存使用率一直上身,沒有下降,就說明很可能存在內存泄露。
對于申請、使用內存比較緩慢的應用程序,可以通過下面的命令,觀測一天乃至一周內內存使用率的變化:
for
((i=0;i<100000;i++)); do pidstat -p `pidof YourProgram` -tr | tee
-a thread_mem_static.txt; sleep 10; done
如果上面顯示的RSS的內存隨著時間推移不斷增加,且不符合程序預期,那么很可能存在內存泄露。
1.定位內存泄露的線程或代碼位置
檢查主進程的每個線程的page
fault的頻率,雖然page
fault頻率高的不一定有內存泄露,但有內存泄露的線程的page
fault的頻率一定很高。而體現每個線程Page
fault頻率的指標就是上圖中每個線程的minflt/s值,如果它的值一直偏高,就說明該線程反復申請內存或者不停在棧上使用buffer,此時就需要利用gdb打印出每個線程信息,可以參考下面的gdb命令:
gdb
-q --batch --ex "thread apply all bt" -p `pidof tmem`
根據上面對應的線程號找到相應函數,然后進行跟蹤,可以參考下面的示例:
上圖中顯示線程14178
(mem_funcs)線程頻繁使用新的內存,查看代碼,果然存在內存泄露:
需要強調的是,只有RSS不一直增加,哪怕minflt/s一直增加,也表明沒有內存泄露,比如下面的測試程序,頻繁使用棧上空間:
void
internal_mem_funcs(void)
{
long
int test[MAX_BUF_LEN] = {0,};
//long
int * test = (long int *)malloc(MAX_BUF_LEN * sizeof(long int));
int
i = 0;
for
(i = 0; i < MAX_BUF_LEN; i++) {
test[i]
= random();
}
return;
}
它的pidstat統計圖如下:
2.常見的內存泄露方式
筆者最近分析了一個系統服務進程內存泄露的問題,下面總結了一些代碼中很容易出現內存泄露的地方:函數正常成功執行的時候有釋放內存,但在執行異常退出的時候,沒有釋放所有先前申請的內存;
對類似strdup()/strndup()/g_strdup()的函數的返回值,使用完之后,沒有釋放內存的意識;
不同模塊或者層次的代碼相互調用的時候,沒有統一約定好是調用者申請內存、釋放內存還是被調用者申請、釋放內存,抑或是調用者申請/釋放內存,被調用者釋放/申請內存,導致后面遺忘釋放內存或者重復釋放內存;
Java/c++中對異常處理的流程中,遺忘沒有釋放內存;
使用了一些不太熟悉的第三方庫代碼,對類似句柄、描述符、對象相關的API了解不夠深入,導致沒有也不知道該如何釋放內存。
總結
以上是生活随笔為你收集整理的linux 内存泄漏 定位,一种内存泄露检查和定位的方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NFC基础知识学习
- 下一篇: intel i218v千兆网卡 linu