C++內存機制中內存泄露、內存溢出、內存越界和內存泄漏原因分析

在用C++做底層驅動時,經常會遇到內存不足的警告,往往是因爲內存出現溢出、泄露或者越界等原因。

內存溢出(out of memory)

   是指程序在申請內存時,沒有足夠的內存空間供其使用。

內存泄漏(memory leak)

   是指程序申請的內存,用完後沒有釋放已申請的內存空間,佔用有用內存。

二者關係:內存泄漏的堆積最終會導致內存溢出內存溢出,就是你要的內存空間超過了系統實際分配給你的空間,此時系統相當於沒法滿足你的需求,就會報內存溢出的錯誤。

內存泄漏是指你向系統申請分配內存進行使用(new),可是使用完了以後卻不歸還(delete),結果你申請到的那塊內存你自己也不能再訪問(也許你把它的地址給弄丟了),而系統也不能再次將它分配給需要的程序。也無法被垃圾回收器回收,因爲找不到他的任何信息。
簡單理解,內存溢出就是要求分配的內存超出了系統所給的。內存泄漏是指向系統申請分配內存進行使用(new),但是用完後不歸還(delete),導致佔用有效內存。

內存泄漏可分爲4類:

1.常發性內存泄漏
引起內存泄漏的代碼會被很多次執行,每次執行的時候都會導致內存泄漏
2.偶發性內存泄漏
在某些特定的環境下執行引起內存泄漏的代碼,纔會引起內存泄漏
從以上兩種內存泄漏的方式來看,測試環境和測試方法在程序生命週期的重要性是不可或缺的。
3.一次性內存泄漏
代碼只會執行一次,但總有一塊內存發生泄漏,多見於構造類的時候,析構函數沒有釋放內存。
4.隱式泄漏
程序運行過程中不斷的分配內存,直到結束時才釋放內存,但一般服務器程序會運行較長的時間,不及時釋放也會導致內存耗盡以至於內存泄漏。
綜上所述,一次性內存泄漏對用戶的程序維護是沒有什麼實質性的傷害,但在實際生活中,我們還是儘可能要避免此類的事件發生。
內存越界
是指向系統申請一塊內存後,使用時卻超出申請範圍。比如一些操作內存的函數:sprintf、strcpy、strcat、vsprintf、memcpy、memset、memmove。當造成內存泄漏的代碼運行時,所帶來的錯誤是無法避免的,通常會造成
1.破壞了堆中內存內存分配信息數據
2.破壞了程序其他對象的內存空間
3.破壞了空閒內存塊
附:如果在之前你的程序運行一切正常,但因爲你新增了幾個類的成員變量或者修改了一部分代碼(前提是保證你的這些修改是完全正確的)而導致程序發生錯誤,則因考慮是否是內存被破壞的原因了,重點排查內存是否越界。
緩衝區溢出(棧溢出)
程序爲了臨時存取數據的需要,一般會分配一些內存空間稱爲緩衝區。如果向緩衝區中寫入緩衝區無法容納的數據,機會造成緩衝區以外的存儲單元被改寫,稱爲緩衝區溢出。而棧溢出是緩衝區溢出的一種,原理也是相同的。分爲上溢出和下溢出。其中,上溢出是指棧滿而又向其增加新的數據,導致數據溢出;下溢出是指空棧而又進行刪除操作等,導致空間溢出。

內存泄漏的原因
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(),然後提交物理存儲器後,沒有釋放掉

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