解釋:內存溢出、內存泄露、內存越界、緩衝區溢出、棧溢出


轉載自:點擊打開鏈接http://blog.csdn.net/sdustliyang/article/details/6899892



內存溢出就是你要求分配的內存超出了系統能給你的,系統不能滿足

需求,於是產生溢出。

================================================================

內存泄漏是指你向系統申請分配內存進行使用(new),可是使用
完了以後卻不歸還(delete),結果你申請到的那塊內存你自己也不能
再訪問(也許你把它的地址給弄丟了),而系統也不能再次將它分配
給需要的程序。一個盤子用盡各種方法只能裝4 個果子,你裝了5
個,結果掉倒地上不能吃了。這就是溢出!比方說棧,棧滿時再做進
棧必定產生空間溢出,叫上溢,棧空時再做退棧也產生空間溢出,稱
爲下溢。就是分配的內存不足以放下數據項序列,稱爲內存溢出.
以發生的方式來分類,內存泄漏可以分爲4 類:
1. 常發性內存泄漏。發生內存泄漏的代碼會被多次執行到,每次被
執行的時候都會導致一塊內存泄漏。
2. 偶發性內存泄漏。發生內存泄漏的代碼只有在某些特定環境或操
作過程下才會發生。常發性和偶發性是相對的。對於特定的環境,偶
發性的也許就變成了常發性的。所以測試環境和測試方法對檢測內存
泄漏至關重要。
3. 一次性內存泄漏。發生內存泄漏的代碼只會被執行一次,或者由
於算法上的缺陷,導致總會有一塊僅且一塊內存發生泄漏。比如,在
類的構造函數中分配內存,在析構函數中卻沒有釋放該內存,所以內
存泄漏只會發生一次。
4. 隱式內存泄漏。程序在運行過程中不停的分配內存,但是直到結
束的時候才釋放內存。嚴格的說這裏並沒有發生內存泄漏,因爲最終
程序釋放了所有申請的內存。但是對於一個服務器程序,需要運行幾
天,幾周甚至幾個月,不及時釋放內存也可能導致最終耗盡系統的所
有內存。所以,我們稱這類內存泄漏爲隱式內存泄漏。
從用戶使用程序的角度來看,內存泄漏本身不會產生什麼危害,作爲
一般的用戶,根本感覺不到內存泄漏的存在。真正有危害的是內存泄
漏的堆積,這會最終消耗盡系統所有的內存。從這個角度來說,一次
性內存泄漏並沒有什麼危害,因爲它不會堆積,而隱式內存泄漏危害

性則非常大,因爲較之於常發性和偶發性內存,泄漏它更難被檢測到

=================================================================

內存越界:

何謂內存訪問越界,簡單的說,你向系統申請了一塊內存,在使用這塊內存的時候,超出了你申請的範圍。

內存越界使用,這樣的錯誤引起的問題存在極大的不確定性,有時大,有時小,有時可能不會對程序的運行產生影響,正是這種不易重現的錯誤,纔是最致命的,一旦出錯破壞性極大。


什麼原因會造成內存越界使用呢?有以下幾種情況,可供參考:
例1:
        char buf[32] = {0};
        for(int i=0; i<n; i++)// n < 32 or n > 32
        {
            buf[i] = 'x';
        }
        ....        
例2:
        char buf[32] = {0};
        string str = "this is a test sting !!!!";
        sprintf(buf, "this is a test buf!string:%s", str.c_str()); //out of buffer space
        ....    
例3:
        string str = "this is a test string!!!!";
        char buf[16] = {0};
        strcpy(buf, str.c_str()); //out of buffer space
        
類似的還存在隱患的函數還有:strcat,vsprintf等
同樣,memcpy, memset, memmove等一些內存操作函數在使用時也一定要注意。
        
當這樣的代碼一旦運行,錯誤就在所難免,會帶來的後果也是不確定的,通常可能會造成如下後果:

1.破壞了堆中的內存分配信息數據,特別是動態分配的內存塊的內存信息數據,因爲操作系統在分配和釋放內存塊時需要訪問該數據,一旦該數據被破壞,以下的幾種情況都可能會出現。 
        *** glibc detected *** free(): invalid pointer:
        *** glibc detected *** malloc(): memory corruption:
        *** glibc detected *** double free or corruption (out): 0x00000000005c18a0 ***
        *** glibc detected *** corrupted double-linked list: 0x00000000005ab150 ***        

2.破壞了程序自己的其他對象的內存空間,這種破壞會影響程序執行的不正確性,當然也會誘發coredump,如破壞了指針數據。

3.破壞了空閒內存塊,很幸運,這樣不會產生什麼問題,但誰知道什麼時候不幸會降臨呢?

通常,代碼錯誤被激發也是偶然的,也就是說之前你的程序一直正常,可能由於你爲類增加了兩個成員變量,或者改變了某一部分代碼,coredump就頻繁發生,而你增加的代碼絕不會有任何問題,這時你就應該考慮是否是某些內存被破壞了。

排查的原則,首先是保證能重現錯誤,根據錯誤估計可能的環節,逐步裁減代碼,縮小排查空間。
檢查所有的內存操作函數,檢查內存越界的可能。常用的內存操作函數:
sprintf snprintf 
vsprintf vsnprintf
strcpy strncpy strcat 
memcpy memmove memset bcopy

如果有用到自己編寫的動態庫的情況,要確保動態庫的編譯與程序編譯的環境一致。

=================================================================

緩衝區溢出:

緩衝區溢出是指當計算機向緩衝區內填充數據位數時超過了緩衝區本身的容量溢出的數據覆蓋在合法數據上,理想的情況是程序檢查數據長度並不允許輸入超過緩衝區長度的字符,但是絕大多數程序都會假設數據長度總是與所分配的儲存空間相匹配,這就爲緩衝區溢出埋下隱患.操作系統所使用的緩衝區 又被稱爲"堆棧". 在各個操作進程之間,指令會被臨時儲存在"堆棧"當中,"堆棧"也會出現緩衝區溢出。

棧溢出:

 棧溢出就是緩衝區溢出的一種。 由於緩衝區溢出而使得有用的存儲單元被改寫,往往會引發不可預料的後果。程序在運行過程中,爲了臨時存取數據的需要,一般都要分配一些內存空間,通常稱這些空間爲緩衝區。如果向緩衝區中寫入超過其本身長度的數據,以致於緩衝區無法容納,就會造成緩衝區以外的存儲單元被改寫,這種現象就稱爲緩衝區溢出。

  棧溢出就是緩衝區溢出的一種。


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