aix內存泄露


介紹使用腳本判斷內存泄漏的簡便方法
  
Document #: 2811995H29001 
Body: 
[標題] 
介紹使用腳本判斷內存泄漏的簡便方法
內容提要:
本文份四個部分介紹如何使用提供的腳本定位分析應用內存泄漏 
一,前言
二,內存使用介紹
三,腳本使用介紹
四,示例分析
五,總結
說明: 
介紹使用腳本判斷內存泄漏的簡便方法 
一,前言 
應用內存泄漏是UNIX 系統中比較常見的一種現象,如何定位並確定內存泄漏的
應用是一個相對復雜的過程。本文將探討內存泄漏的產生,及在AIX 系統中如何利用
提供的腳本,在系統級層面判斷內存泄漏的進程。
二,內存使用介紹 
C 語言中,應用使用malloc() 函數從進程的堆棧中申請內存,而在C++ 中內存的申請
使用是在類的初始化中通過構造函數建立的,包含類及其成員。當進程不再需要部
分內存是,將通過系統free() 函數歸還給操作系統,而在C++ 中則通過析構函數釋放
類的內存。進程終止時,進程的使用的棧的內存將全部歸還給操作系統。如果進程
申請使用的內存不能釋放,而且進程堆棧持續增長,應用可能存在內存泄漏。最終
的結果是進程消耗所有的系統內存,導致應用異常終止,或者是系統啟動自身的保
護機制殺掉進程,進而釋放系統的內存。
操作系統開發者不斷的探求如何更有效的使用、分配內存的策略,在AIX 4.2 – 
5.2 版本中,使用Yorktown 機制分配系統內存,相對於以前的版本,AIX 5.3 中引入
了新的內存分配使用機制watson ,基於rbtree(red-black tree) 結構,提高了malloc 的
性能,同時減少了堆棧的碎片。
三,腳本使用介紹 
本文提供一組腳本,通過這組腳本,可以比較簡單、快速的判斷定位,哪一個進程
產生內存泄漏。腳本名稱post_vg.sh ,使用方法如下:
1) 首先搜集系統的初始狀態,包含每個進程使用的內存情況: 
# ps vg > ps.before 
2) 間隔一段合適的時間后,如15 分鍾,根據應用或系統的情況而定,重新收集系統的狀態 
# ps vg > ps.after 
3) 比較系統的前后狀態,判斷進程的內存使用情況,輸出信息中Delta 表明進程內存的前后
使用情況,如果值增加,其中一個可能的情況就是內存泄漏 
# ./post_vg ps.before ps.after 
腳本的內容如下:
#!/bin/ksh 
# Correlate ps.before and ps.after data .. 
# command output from ps vg 
ONE_FILE=temp_ps_vg 
print_help() { 
print "Version 1.0" 
print "Usage: post_vg.sh [single_file|before_ps after_ps]" 
print " Post process ps vg output " 
print " " 
print " where, " 
print " single_file contains a before and after snapshot" 
print " " 
print " No files specified - assume" 
print " ==> ps_vg.before " 
print " ==> ps_vg.after " 
exit -1 
main() { 
if [[ $1 == "-?" ]] 
then 
print_help 
exit -1 
fi 
if [[ $# == 2 ]] 
then 
cat $1 $2 > $ONE_FILE 
elif [[ $# == 1 ]] 
then 
cat $1 > $ONE_FILE 
else 
cat ps_vg.before ps_vg.after > $ONE_FILE 
fi 
post_vg 
rm $ONE_FILE 
post_vg() { 
cat $ONE_FILE | awk 'BEGIN { 
list_label = "None" 
/PID/ { 
if( list_label == "None" ) 
list_label = "Before" 
else 
list_label = "After" 
next 
pid_list[$1] 
pid_size[$1, list_label ] = $6 
pid_name[$1] = $13 
END { 
printf("%15s\t%10s\t%11s\t%10s\t%10s\n", "pid", \ 
"Name", \ 
"Before Size", \ 
"After Size", \ 
"Delta") 
for( pid in pid_list ) { 
if( (pid,"Before") in pid_size && (pid,"After") in pid_size ) { 
delta = pid_size[pid, "After"] - pid_size[pid, "Before"] 
d_total += delta 
printf("%15s\t%10s\t%11d\t%10d\t%10d\n", \ 
pid, \ 
pid_name[pid], \ 
pid_size[pid, "Before"], \ 
pid_size[pid, "After"], \ 
delta ) 
printf("*** Total Delta %d\n", d_total) 
}' 
main $@ 
四,示例分析 
通過以下的簡單應用,借助以上的腳本,分析系統內存的使用。
測使用例:
#include <stdio.h> 
main() { 
char *ptr; 
int count=0; 
/* 申請系統內存 */ 
for (count=0; count<100000; count++) { 
ptr = (char *)malloc(1024*1024); 
memset(ptr, 0, 1024*1024); 
/* 釋放系統內存,決定應用是否產生內存泄漏。如果生成內存泄漏的應用,需要打開注釋 */ 
/* free(ptr); 
*/ 
sleep(1); 
編譯鏈接以上程序,生成有內存泄漏和沒有內存泄漏兩種情況,應用名稱如下:
memleak : 有內存泄漏
nmemleak :沒有內存泄漏
測試如下:
1) 測試應用沒有內存泄漏
a) 運行nmemleak程序 
# nmemleak
b) 使用命令ps收集系統的狀態 
# ps vg >ps.before
c) nmemleak運行一段時間后,假定30秒,重新收集系統的狀態 
# ps vg >ps.after
d) 使用post_vg.sh分析狀態文件,並查看Delta項是否為0 
# ./post_vg.sh ps.before ps.after
輸出結果如下:
pid Name Before Size After Size Delta
... ... 
284 wait 40 40 0
192946 /usr/sbi 1300 1300 0
168240 nmemleak 1120 1120 0 
119182 /usr/sbi 772 772 0
57792 /usr/sbi 640 640 0
... ...
*** Total Delta 0 
從上面的分析結果可以看出,Delta項值為0,也就是說,可以基本斷定nmemleak沒有內存泄漏。
2) 測試應用有內存泄漏
a) 運行memleak程序 
# memleak
b) 使用ps命令收集系統的初始狀態 
# ps vg >ps.before
c) memleak運行一段時間后,假定30秒,重新運行ps命令收集系統的狀態 
# ps vg >ps.after
d) 使用post_vg.sh分析狀態文件,查看Delta項 
# post_vg.sh ps.before ps.after
查卡分析結果如下:
pid Name Before Size After Size Delta 
... ... 
90456 /usr/ccs 128 128 0 
110734 /usr/sbi 1520 1520 0 
209368 telnetd 624 624 0 
168274 memleak 13408 42080 28672 
147862 /usr/sbi 212 212 0 
36882 pilegc 144 144 0 
115076 /usr/sbi 1040 1040 0 
78120 rpc.lockd 204 204 0 
284 wait 40 40 0 
... ... 
*** Total Delta 28672 
分析以上結果,可以看到,memleak 應用使用的進程內存增加了28672K 字節,明顯存在內存
泄漏。接下來,要做的是定位應用那個函數造成的內存泄漏,需要按行定位代碼,或者使用
第三方的內存檢測工具,如Purify 。
五,總結 
決定於應用的復雜程度,確定和定位內存泄漏,難度會相應的不同,結合系統提供的其他工具, 
如svmon ,和更專業的內存使用分析工具判斷應用內存的使用情況。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM