記憶體分配 1

2021-04-28 16:30:53 字數 1982 閱讀 9536

記憶體分配方式有三種:(1

)從靜態儲存區域分配。內存在程式編譯的時候就已經分配好,這塊內存在程式的整個執行期間都存在。例如全域性變數,

static

變數。(2)

在棧上建立。在執行函式時,函式內區域性變數的儲存單元都可以在棧上建立,函式執行結束時這些儲存單元自動被釋放。棧記憶體分配運算內置於處理器的指令集中,效率很高,但是分配的記憶體容量有限。(3

)從堆上分配,亦稱動態記憶體分配。程式在執行的時候用

malloc

或new

申請任意多少的記憶體,程式設計師自己負責在何時用

free

或delete

釋放記憶體。動態記憶體的生存期由我們決定,使用非常靈活,但問題也最多。

發生記憶體錯誤是件非常麻煩的事情。編譯器不能自動發現這些錯誤,通常是在程式執行時才能捕捉到。而這些錯誤大多沒有明顯的症狀,時隱時現,增加了改錯的難度。有時使用者怒氣沖沖地把你找來,程式卻沒有發生任何問題,你一走,錯誤又發作了。

常見的記憶體錯誤及其對策如下:

u記憶體分配未成功,卻使用了它。

程式設計新手常犯這種錯誤,因為他們沒有意識到記憶體分配會不成功。常用解決辦法是,在使用記憶體之前檢查指標是否為

null

。如果指標

p是函式的引數,那麼在函式的入口處用

assert(p!=null)進行檢查。如果是用malloc或new來申請記憶體,應該用if(p==null) 或if(p!=null)進行防錯處理。

u記憶體分配雖然成功,但是尚未初始化就引用它。

犯這種錯誤主要有兩個起因:一是沒有初始化的觀念;二是誤以為記憶體的預設初值全為零,導致引用初值錯誤(例如陣列)。

記憶體的預設初值究竟是什麼並沒有統一的標準,儘管有些時候為零值,我們寧可信其無不可信其有。所以無論用何種方式建立陣列,都別忘了賦初值,即便是賦零值也不可省略,不要嫌麻煩。

u記憶體分配成功並且已經初始化,但操作越過了記憶體的邊界。

例如在使用陣列時經常發生下標「多

1」或者「少

1」的操作。特別是在

for迴圈語句中,迴圈次數很容易搞錯,導致陣列操作越界。

u忘記了釋放記憶體,造成記憶體洩露。

動態記憶體的申請與釋放必須配對,程式中

malloc

與free

的使用次數一定要相同,否則肯定有錯誤(

new/delete

同理)。

u釋放了記憶體卻繼續使用它。

有三種情況:(1

)程式中的物件呼叫關係過於複雜,實在難以搞清楚某個物件究竟是否已經釋放了記憶體,此時應該重新設計資料結構,從根本上解決物件管理的混亂局面。(2

)函式的

return

語句寫錯了,注意不要返回指向「棧記憶體」的「指標」或者「引用」,因為該內存在函式體結束時被自動銷毀。(3

)使用free

或delete

釋放了記憶體後,沒有將指標設定為

null

。導致產生「野指標」。

l【規則

-1用malloc或new申請記憶體之後,應該立即檢查指標值是否為null。防止使用指標值為null的記憶體。 l

【規則

-2不要忘記為陣列和動態記憶體賦初值。

防止將未被初始化的記憶體作為右值使用。

l【規則

-3避免陣列或指標的下標越界,特別要當心發生「多

1」或者「少

1」操作。

l【規則

-4動態記憶體的申請與釋放必須配對,防止記憶體洩漏。

l【規則

-5

free

或delete

釋放了記憶體之後,立即將指標設定為

null

,防止產生「野指標」。

1 動態記憶體分配

1.1 c語言的資料結構,通常都是固定大小的,比如 陣列有固定的大小,而每個元素也有固定的長度。這樣對程式有一定限制,例如 我們要使用陣列來儲存乙個班級的學生資訊,陣列的長度指定多大合適呢?太大浪費空間,太小不夠用。這時候就會用到記憶體的動態分配。1.2 記憶體分配函式 malloc函式,分配記憶體...

記憶體分配 1 空閒鍊錶

posted on 六月 29,2007 byarrowpig1979 記憶體分配是所有成功的庫都要費大量心力去做好的事情,除非是對performance很高的需求,至少我現在在工作中很少需要自己來寫記憶體分配策略。我始終覺得一些經典的庫,像stl,loki,boost是最好的教材。讀書也要講究方法...

記憶體分配 Go記憶體管理 記憶體分配一

go作為乙個比較新晚 新 的語言,自然借鑑前輩們的優點,比如說語言本身負責記憶體管理 對協程和高併發的高優支援 簡單高效的語法等。本篇及後續的幾篇要講的就是還沒提到的比較複雜的記憶體管理。學習記憶體管理 分配 前,如果有jvm的記憶體管理的基礎,會變得非常簡單,如果是第一次接觸記憶體管理,在看完go...