內存泄漏

    今天在使用OSS軟件【對象存儲(Object Storage Service,簡稱OSS),是阿里雲對外提供的海量、安全和高可靠的雲存儲服務。RESTful API的平臺無關性,容量和處理能力的彈性擴展,按實際容量付費真正使您專注於核心業務。】上傳官網所需的客戶端資源時,發現上傳文件過多時,會出現速度慢,類似卡死、閃退這種現象。經過查看進程管理器發現它佔用的內存太多,經驗豐富的主程說這是內存泄漏造成的。我這才認識到,原來寫代碼時檢查的內存泄漏,是爲了防止佔用空間大啊!於是,傳完資源後,趕緊百度了一下 。沒想到啊,一個經常做的操作,讓我對內存泄漏有了一個更深的瞭解。   

   內存泄漏也稱作“存儲滲漏”,用動態存儲分配函數動態開闢的空間,在使用完畢後未釋放,結果導致一直佔據該內存單元。直到程序結束。(其實說白了就是該內存空間使用完畢之後未回收)即所謂內存泄漏。

    內存泄漏形象的比喻是“操作系統可提供給所有進程的存儲空間正在被某個進程榨乾”,最終結果是程序運行時間越長,佔用存儲空間越來越多,最終用盡全部存儲空間,整個系統崩潰。所以“內存泄漏”是從操作系統的角度來看的。這裏的存儲空間並不是指物理內存,而是指虛擬內存大小,這個虛擬內存大小取決於磁盤交換區設定的大小。由程序申請的一塊內存,如果沒有任何一個指針指向它,那麼這塊內存就泄漏了。

    內存泄漏分類:

  1. 常發性:發生內存泄漏的代碼會被多次執行到,每次被執行的時候都會導致一塊內存泄漏。

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

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

  4. 隱式:程序在運行過程中不停的分配內存,但是直到結束的時候才釋放內存。嚴格的說這裏並沒有發生內存泄漏,因爲最終程序釋放了所有申請的內存。但是對於一個服務器程序,需要運行幾天、幾周甚至幾個月,不及時釋放內存也可能導致最終耗盡系統的所有內存。所以,我們稱這類內存泄漏爲隱式內存泄漏。

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

             內存泄漏表現:


  1. cpu資源耗盡:估計是機器沒有反應了,鍵盤,鼠標,以及網絡等等。在中了計算機病毒的設備上非常常見。

  2. 進程id耗盡:沒法創建新的進程了,串口或者telnet都沒法創建了。

  3. 硬盤耗盡: 機器要死了,交換內存沒法用,日誌也沒法用了,死是很正常的。

  4. 內存泄漏或者內存耗盡:新的連接無法創建,free的內存比較少。發生內存泄漏的程序很多,但是要想產生一定的後果,就需要這個進程是無限循環的,是個服務進程。當然,內核也是無限循環的,所以,如果內核發生了內存泄漏,情況就更加不妙。內存泄漏是一種很難定位和跟蹤的錯誤,目前還沒看到有什麼好用的工具(當然,用戶空間有一些工具,有靜態分析的,也會動態分析的,但是找內核的內存泄漏,沒有好的開源工具)。

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

       一般我們常說的內存泄漏是指堆內存的泄漏。

        堆內存是指程序從堆中分配的,大小任意的(內存塊的大小可以在程序運行期決定),使用完後必須顯式釋放的內存。

        應用程序一般使用malloc,realloc,new等函數從堆中分配到一塊內存,使用完後,程序必須負責相應的調用free或delete釋放該內存塊,否則,這塊內存就不能被再次使用,我們就說這塊內存泄漏了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章