1. 程式人生 > >一個很難發現的記憶體洩漏

一個很難發現的記憶體洩漏

  當你的資源釋放以後,再去訪問時,就會出現各種錯誤,比如物件返回空,資源不存在等等,這些錯誤都是編譯的時候語法合理的,但是一旦執行到了這裡,肯定就會出錯了(這一塊如果沒被執行的話,還是發現不了錯誤的)。而且很難找到這個錯誤的原因(不在於這個錯誤有多麼的難,而是程式碼太多,關係太複雜,沒有很好地條理去分析,邏輯混亂了以後,就會覺得太可怕了)。因此,找BUG需要時刻保持清醒的頭腦,這個BUG我昨天從下午到晚上十點多,一直找都沒解出來,今天上午剛起床,來到自習室,冷靜的分析了片刻,很快就看出來了問題的癥結。

 

設想一下如果申請的堆記憶體不夠我放下想要的資料,但是我確實又把所有想要的資料都放入了其中,會發生什麼???

這是一個特別奇葩的記憶體洩漏,我之前根本就沒想過粗心會導致這種錯誤!!!

當你(new)申請的堆空間只夠放下一個物件時(如上圖),實際上你卻可以用這個指標陣列存放不止一個物件,當你存放了2個及以上物件時(也就是超過了申請的堆記憶體空間),這個時候,編譯合法,執行也正常(這點很奇怪,但是這是事實),不過當你的程式退出時,會呼叫解構函式,如果你在解構函式中手動的釋放這塊記憶體的話,就會出現記憶體洩漏了!!!!!!!!!!

原因:

因為原來只分配了一個物件的記憶體空間,但是你卻向這塊記憶體中放了不止一個物件(這樣做 語法正確,執行也正確),因此delete這個指標的時候,只會釋放一個記憶體的空間,因此導致了其餘物件的記憶體空間沒有釋放,出現了記憶體洩漏被其他程式檢測到(可能是核心又或者是相關的支援程式亦或是程式本身有監測機制),就會提示錯誤了。

 

關於new申請記憶體的個人看法:

如上所述,關於 “申請的堆空間只夠放下一個物件時(如上圖),實際上你卻可以用這個指標陣列存放不止一個物件” 為什麼能夠成功的正常執行。

首先來反推一下,程式能夠正常的執行(只是在退出的時候呼叫一些解構函式釋放記憶體空間出錯)說明我實實在在的使用了少量申請到的記憶體存放了

超過這個記憶體塊大小的資料,並且這些資料是能夠被正常訪問到的,也就是說這塊記憶體區域對應用程式來說是合法的(否則會報錯“記憶體訪問衝突”),

儘管設計者並沒有申請這麼多的記憶體。

再聯想一下裝置的這些硬體資源全部都由核心管理以及分配給應用程式,並且這些由核心管理的記憶體空間是以最小單位頁被分配給應用程式的,所以

申請一個物件的空間的時候,核心會以頁為單位分配記憶體空間給應用程式,所以就會出現  “申請的堆空間只夠放下一個物件時(如上圖),實際上你卻

可以用這個指標陣列存放不止一個物件”  的情況了!!!