記憶體的動態分配與靜態分配

2021-09-01 22:32:31 字數 2812 閱讀 9938

記憶體的靜態分配和動態分配的區別主要是兩個:

一是時間不同。靜態分配發生在程式編譯和連線的時候。動態分配則發生在程式調入和執行的時候。

二是空間不同。堆都是動態分配的,沒有靜態分配的堆。棧有2種分配方式:靜態分配和動態分配。靜態分配是編譯器完成的,比如區域性變數的分配。動態分配由函式malloc進行分配。不過棧的動態分配和堆不同,他的動態分配是由編譯器進行釋放,無需我們手工實現。    

對於乙個程序的記憶體空間而言,可以在邏輯上分成3個部份:**區,靜態資料區和動態資料區。動態資料區一般就是「堆疊」。「棧(stack)」和「堆(heap)」是兩種不同的動態資料區,棧是一種線性結構,堆是一種鏈式結構。程序的每個執行緒都有私有的「棧」,所以每個執行緒雖然**一樣,但本地變數的資料都是互不干擾。乙個堆疊可以通過「基位址」和「棧頂」位址來描述。全域性變數和靜態變數分配在靜態資料區,本地變數分配在動態資料區,即堆疊中。程式通過堆疊的基位址和偏移量來訪問本地變數。

一般,用static修飾的變數,全域性變數位於靜態資料區。函式呼叫過程中的引數,返回位址,ebp和區域性變數都採用棧的方式存放。

所謂動態記憶體分配就是指在程式執行的過程中動態地分配或者**儲存空間的分配記憶體的方法。動態記憶體分配不象陣列等靜態記憶體分配方法那樣需要預先分配儲存空間,而是由系統根據程式的需要即時分配,且分配的大小就是程式要求的大小。

例如我們定義乙個float型陣列:float score[100];   

但是,在使用陣列的時候,總有乙個問題困擾著我們:陣列應該有多大?在很多的情況下,你並不能確定要使用多大的陣列,比如上例,你可能並不知道我們要定義的這個陣列到底有多大,那麼你就要把陣列定義得足夠大。這樣,你的程式在執行時就申請了固定大小的你認為足夠大的記憶體空間。即使你知道你想利用的空間大小,但是如果因為某種特殊原因空間利用的大小有增加或者減少,你又必須重新去修改程式,擴大陣列的儲存範圍。這種分配固定大小的記憶體分配方法稱之為靜態記憶體分配。但是這種記憶體分配的方法存在比較嚴重的缺陷,特別是處理某些問題時:在大多數情況下會浪費大量的記憶體空間,在少數情況下,當你定義的陣列不夠大時,可能引起下標越界錯誤,甚至導致嚴重後果。 

我們用動態記憶體分配就可以解決上面的問題. 所謂動態記憶體分配就是指在程式執行的過程中動態地分配或者**儲存空間的分配記憶體的方法。動態記憶體分配不象陣列等靜態記憶體分配方法那樣需要預先分配儲存空間,而是由系統根據程式的需要即時分配,且分配的大小就是程式要求的大小。從以上動、靜態記憶體分配比較可以知道動態記憶體分配相對於靜態記憶體分配的特點: 

1、不需要預先分配儲存空間;

2、分配的空間可以根據程式的需要擴大或縮小。 

要實現根據程式的需要動態分配儲存空間,就必須用到malloc函式.

malloc函式的原型為:void *malloc (unsigned int size) 其作用是在記憶體的動態儲存區中分配乙個長度為size的連續空間。其引數是乙個無符號整形數,返回值是乙個指向所分配的連續儲存域的起始位址的指標。還有一點必須注意的是,當函式未能成功分配儲存空間(如記憶體不足)就會返回乙個null指標。所以在呼叫該函式時應該檢測返回值是否為null並執行相應的操作。

靜態記憶體是在程式一開始執行就會分配記憶體,直到程式結束了,記憶體才被釋放。

動態記憶體是在程式呼叫在程式中定義的函式時才被分配,函式呼叫結束了,動態記憶體就釋放。

static int a;這是定義了乙個靜態的變數

int a;這是定義了乙個動態的變數;

靜態記憶體可以用於求階層。

例如:jiechen(int i)

#include"stdio.h"

main()

執行輸入3

結果為1!=1

2!=2

3!=3

由malloc系統函式分配的記憶體就是從堆上分配記憶體。從堆上分配的記憶體一定要自己釋放。用free釋放,不然就是術語——「記憶體洩露」(或是「記憶體漏洞」)—— memory leak。於是,系統的可分配記憶體會隨malloc越來越少,直到系統崩潰。還是來看看「棧記憶體」和「堆記憶體」的差別吧。

棧記憶體分配

—————

char*

allocstrfromstack()

堆記憶體分配

—————

char*

allocstrfromheap(int len)

對於第乙個函式,那塊pstr的內存在函式返回時就被系統釋放了。於是所返回的char*什麼也沒有。而對於第二個函式,是從堆上分配記憶體,所以哪怕是程式退出時,也不釋放,所以第二個函式的返回的記憶體沒有問題,可以被使用。但一定要呼叫free釋放,不然就是memory leak!

在堆上分配記憶體很容易造成記憶體洩漏,這是c/c++的最大的「克星」,如果你的程式要穩定,那麼就不要出現memory leak。所以,我還是要在這裡千叮嚀萬囑付,在使用malloc系統函式(包括calloc,realloc)時千萬要小心。

記得有乙個unix上的服務應用程式,大約有幾百的c檔案編譯而成,執行測試良好,等使用時,每隔三個月系統就是down一次,搞得許多人焦頭爛額,查不出問題所在。只好,每隔兩個月人工手動重啟系統一次。出現這種問題就是memery leak在做怪了,在c/c++中這種問題總是會發生,所以你一定要小心。乙個rational的檢測工作——purify,可以幫你測試你的程式有沒有記憶體洩漏。

我保證,做過許多c/c++的工程的程式設計師,都會對malloc或是new有些感冒。當你什麼時候在使用malloc和new時,有一種輕度的緊張和惶恐的感覺時,你就具備了這方面的修養了。

對於malloc和free的操作有以下規則:

1) 配對使用,有乙個malloc,就應該有乙個free。(c++中對應為new和delete)

2) 盡量在同一層上使用,不要像上面那種,malloc在函式中,而free在函式外。最好在同一呼叫層上使用這兩個函式。

3) malloc分配的記憶體一定要初始化。free後的指標一定要設定為null。    

動態分配與靜態分配記憶體

記憶體的靜態分配和動態分配的區別主要是兩個 一是時間不同。靜態分配發生在程式編譯和連線的時候。動態分配則發生在程式調入和執行的時候。二是空間不同。堆都是動態分配的,沒有靜態分配的堆。棧有2種分配方式 靜態分配和動態分配。靜態分配是編譯器完成的,比如區域性變數的分配。動態分配由函式malloc進行分配...

靜態分配記憶體和動態分配記憶體

首先,在使用動態分配記憶體技術前,必須明白自己在做什麼,這樣做與其它的方法有什麼不同,特別是會產生哪些負面影響,天下沒有免費的午餐。動態分配記憶體與靜態分配記憶體的區別 1 靜態記憶體分配是在編譯時完成的,不需要占用cpu資源 動態分配記憶體是在執行時完成的,動態記憶體的分配與釋放需要占用cpu資源...

動態分配記憶體與靜態記憶體分配如何選擇

首先,在使用動態分配記憶體技術前,必須明白自己在做什麼,這樣做與其它的方法有什麼不同,特別是會產生哪些負面影響,天下沒有免費的午餐。動態分配記憶體與靜態分配記憶體的區別 1 靜態記憶體分配是在編譯時完成的,不需要占用cpu資源 動態分配記憶體是在執行時完成的,動態記憶體的分配與釋放需要占用cpu資源...