記憶體洩露的原因

記憶體洩漏是怎麼回事?為什麼會記憶體洩漏?是什麼?下面就由小編告訴大家吧!

  記憶體洩漏是什麼

  簡單的說就是申請了一塊記憶體空間,使用完畢後沒有釋放掉。它的一般表現方式是程式執行時間越長,佔用記憶體越多,最終用盡全部記憶體,整個系統崩潰。由程式申請的一塊記憶體,且沒有任何一個指標指向它,那麼這塊記憶體就洩露了。

  

  1.new,malloc後沒有delete,free

  2.建立核心物件***比如CreateFile,CreateMutex,CreateThread***,後沒有釋放核心物件控制代碼.

  3.建立記憶體對映檔案,CreateFileMapping,MapViewOfFile後沒有CloseHandle******,UnMapviewofFile

  4.建立GDI物件後,比如LoadIcon,LoadImage,CreateImageList等等,沒有Destroy掉

  5.建立DC後,比如GetDC******, 沒有釋放DC控制代碼

  6.保留虛擬地址空間 VirtualAlloc******,然後提交物理儲存器後,沒有釋放掉。

        記憶體洩漏的分類

  以發生的方式來分類,記憶體洩漏可以分為4類:

  ***1***. 常發性記憶體洩漏。

  發生記憶體洩漏的程式碼會被多次執行到,每次被執行的時候都會導致一塊記憶體洩漏。

  ***2***. 偶發性記憶體洩漏。

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

  ***3***. 一次性記憶體洩漏。

  發生記憶體洩漏的程式碼只會被執行一次,或者由於演算法上的缺陷,導致總會有一塊僅且一塊記憶體發生洩漏。比如,在類的建構函式中分配記憶體,在解構函式中卻沒有釋放該記憶體,所以記憶體洩漏只會發生一次。

  ***4***. 隱式記憶體洩漏。

  程式在執行過程中不停的分配記憶體,但是直到結束的時候才釋放記憶體。嚴格的說這裡並沒有發生記憶體洩漏,因為最終程式釋放了所有申請的記憶體。但是對於一個伺服器程式,需要執行幾天,幾周甚至幾個月,不及時釋放記憶體也可能導致最終耗盡系統的所有記憶體。所以,我們稱這類記憶體洩漏為隱式記憶體洩漏。

  記憶體洩漏的危害

  從使用者使用程式的角度來看,記憶體洩漏本身不會產生什麼危害,作為一般的使用者,根本感覺不到記憶體洩漏的存在。真正有危害的是記憶體洩漏的堆積,這會最終消耗盡系統所有的記憶體。從這個角度來說,一次性記憶體洩漏並沒有什麼危害,因為它不會堆積,而隱式記憶體洩漏危害性則非常大,因為較之於常發性和偶發性記憶體洩漏它更難被檢測到。

        記憶體洩漏的表現

  記憶體洩漏或者是說,資源耗盡後,系統會表現出什麼現象哪?

  cpu資源耗盡:估計是機器沒有反應了,鍵盤,滑鼠,以及網路等等。這個在windows上經常看見,特別是中了毒。

  程序id耗盡:沒法建立新的程序了,串列埠或者telnet都沒法建立了。

  硬碟耗盡: 機器要死了,交換記憶體沒法用,日誌也沒法用了,死是很正常的。

  記憶體洩漏或者記憶體耗盡:新的連線無法建立,free的記憶體比較少。發生記憶體洩漏的程式很多,但是要想產生一定的後果,就需要這個程序是無限迴圈的,是個服務程序。當然,核心也是無限迴圈的,所以,如果核心發生了記憶體洩漏,情況就更加不妙。記憶體洩漏是一種很難定位和跟蹤的錯誤,目前還沒看到有什麼好用的工具***當然,使用者空間有一些工具,有靜態分析的,也會動態分析的,但是找核心的記憶體洩漏,沒有好的開源工具***

  記憶體洩漏和物件的引用計數有很大的關係,再加上c/c++都沒有自動的垃圾回收機制,如果沒有手動釋放記憶體,問題就會出現。如果要避免這個問題,還是要從程式碼上入手,良好的編碼習慣和規範,是避免錯誤的不二法門。

  一般我們常說的記憶體洩漏是指堆記憶體的洩漏。

  堆記憶體是指程式從堆中分配的,大小任意的***記憶體塊的大小可以在程式執行期決定***,使用完後必須顯示釋放的記憶體。

  應用程式一般使用malloc,realloc,new等函式從堆中分配到一塊記憶體,使用完後,程式必須負責相應的呼叫free或delete釋放該記憶體塊,否則,這塊記憶體就不能被再次使用,我們就說這塊記憶體洩漏了。