Memory Leak(內存泄漏)問題總結(轉)


最近聽了一些關於Memory Leak(內存泄漏)的seminar,感覺有些收獲,所以留個記錄,並share給朋友。

1 什么是Memory Leak。 Memory Leak是指由於錯誤或不完備的代碼造成一些聲明的對象實例長期占有內存空間,不能回收。Memory Leak會造成系統性能下降,或造成系統錯誤。

2 Memory存儲模式 我們通常寫的C++或Java Code在內存里邊的存儲狀況概如下圖。

簡單的說,一般局部變量存儲於Stack中,以提高運行問速度。而New出來的變量則將引用信息或指針存儲在Stack中,而將對象本身存儲與Heap區中。

這里感謝俊曉同學看完blog后提供了這如下link,可以讓大家更好的理解什么堆啊,棧啊之類的概念。

http://www.builder.com.cn/2007/1010/544483.shtml

3 編碼產生Memory Leak的原因,及避免   
Memory Leak的原因現歸納出3種,以后要還有,再做補充。  
(1)No Referenced Memory (C++ only)    
Sample 1   a(){    
DKString* s= new DKString();    
 … …   
 … …    
delete s;   
 }       
Sample 2   a(){    
char* buffer = (char*)malloc(64 * sizeof(char);   
 … …   
 … …    
free(buffer);    
}

   C++里邊生成/釋放變量的方式有兩種,new/delete, malloc()/free()。無論用那種方式生成,最后一定要有釋放的動作。
否則,在程序離開變量作用域時,Stack里邊的引用會被自動回收,但Heap里的對象實例本身就將成為被永久遺棄在內存里的No Referenced Memory。   
另外需要注意的是, 如果用new生成的,一定要用delete釋放;
如果用malloc生成的,一定要用free釋放。反之,雖然代碼可以通過編譯,但是會造成很多潛在問題。

   (2)No free Objects/Pointers (C++ and Java)    
Java比C++方便的地方是Java可以自圾回收已經過期的內存垃圾,GC。所以,Java程序員從不用關心delete還是free的問題。
但是碰到下面這種情況,GC也無能為力,更不要說C++了。    
Sample 3    
String[] sa = new String[9999999];    
for (int i = 0; i < 9999999; i++){      
String s = new String(“adfasdfadsfas…adfasdfa”); //a 1MB size string…      
sa[i] = s;    
}    
這段代碼讓GC郁悶的是,當循環結束之前,GC永遠收不到任何空間。
因為GC只能收集那些過期的變量,可是在sa過期之前,可能OutOfMemory已經發生了。    

  (3)No Limited Storage (C++ and Java)   
Sample 4    … …    
While (true){     
Vector.add(obj);   
}   
… …   
像 Vector, hashtable, hashmap, map, arraylist and String StringBuffer… …這樣的工具類自身沒有上限,如果,Developer再不加控制,很容易內存溢出。    
4 如何通過測試發現Memory Leak  
(1)Long Run  
很多時候,微小的Memory Leak不會給我們的系統造成太多的影響,只有當泄露積累到一定程度,問題才會爆發。因此,從理論上說,我們要讓代碼多次重復的Run從而暴露Memory Leak問題。在我們公司,這種測試叫Long Run。所謂Long Run並不一定說一定要讓測試Case跑多么長的時間,而是跑足夠的次數。  
(2)特殊Case  
這是一個Tester的經驗做法,他們相信developer會在大部分正常的程序邏輯里邊考慮和處理Memory Leak問題,但異常條件也許未必,所以,通過適當的臨界測試和特殊case測試,亦或能找到Memory Leak的case.     
個人認為,發現並避免Memory Leak,最重要的還是Developer從程序設計、編碼的時候就在上游把好質量關。否則,真正到Tester發現並定位Memory Leak問題,代價則相當大。   

5 分析Memory Leak的工具  

工欲善其事,必先利其器。這里會搜及並不斷補充一些Memory Leak的分析工具,以滿足Tool People的要求。  
(1)Purify    一般For C Code  
(2)Heap Analyzer    
可以For Java Code  
(3)Java Dump    
這牽涉到另一個Topic,希望以后能有所補充。

http://blog.csdn.net/iloveagile/article/details/3850668

汗死,把內存溢出和內存泄漏混為一談了,后面兩種情況不屬於內存泄漏,而是內存溢出。
內存泄漏通俗的講是指某個程序申請了某塊內存,不用了以后,沒有回收,系統以為該內存還是被占用的,因此該內存【相當於】消失了。
而內存溢出則是程序在申請內存時,沒有足夠的內存空間供其使用。
二者之間的聯系是:內存泄漏如果累積最終也會造成內存溢出

 

 

 

內存溢出 out of memory,是指程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory;比如申請了一個integer,但給它存了long才能存下的數,那就是內存溢出。

內存泄露 memory leak,是指程序在申請內存后,無法釋放已申請的內存空間,一次內存泄露危害可以忽略,但內存泄露堆積后果很嚴重,無論多少內存,遲早會被占光。

memory leak會最終會導致out of memory!

內存溢出就是你要求分配的內存超出了系統能給你的,系統不能滿足需求,於是產生溢出。 
內存泄漏是指你向系統申請分配內存進行使用(new),可是使用完了以后卻不歸還(delete),結果你申請到的那塊內存你自己也不能再訪問(也許你把它的地址給弄丟了),而系統也不能再次將它分配給需要的程序。一個盤子用盡各種方法只能裝4個果子,你裝了5個,結果掉倒地上不能吃了。這就是溢出!
比方說棧,棧滿時再做進棧必定產生空間溢出,叫上溢,棧空時再做退棧也產生空間溢出,稱為下溢。就是分配的內存不足以放下數據項序列,稱為內存溢出. 
   以發生的方式來分類,內存泄漏可以分為4類: 
1. 常發性內存泄漏。
發生內存泄漏的代碼會被多次執行到,每次被執行的時候都會導致一塊內存泄漏。 

2. 偶發性內存泄漏。
發生內存泄漏的代碼只有在某些特定環境或操作過程下才會發生。
常發性和偶發性是相對的。對於特定的環境,偶發性的也許就變成了常發性的。
所以測試環境和測試方法對檢測內存泄漏至關重要。 

3. 一次性內存泄漏。
發生內存泄漏的代碼只會被執行一次,或者由於算法上的缺陷,導致總會有一塊僅且一塊內存發生泄漏。
比如,在類的構造函數中分配內存,在析構函數中卻沒有釋放該內存,所以內存泄漏只會發生一次。 

4. 隱式內存泄漏。程序在運行過程中不停的分配內存,但是直到結束的時候才釋放內存。
嚴格的說這里並沒有發生內存泄漏,因為最終程序釋放了所有申請的內存。
但是對於一個服務器程序,需要運行幾天,幾周甚至幾個月,不及時釋放內存也可能導致最終耗盡系統的所有內存。
所以,我們稱這類內存泄漏為隱式內存泄漏。 
從用戶使用程序的角度來看,內存泄漏本身不會產生什么危害,作為一般的用戶,根本感覺不到內存泄漏的存在。
真正有危害的是內存泄漏的堆積,這會最終消耗盡系統所有的內存。
從這個角度來說,一次性內存泄漏並沒有什么危害,因為它不會堆積,而隱式內存泄漏危害性則非常大,因為較之於常發性和偶發性內存泄漏它更難被檢測到 

http://blog.csdn.net/buutterfly/article/details/6617375

 


免責聲明!

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



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