動態分配記憶體

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

基本介紹

  • 中文名:動態分配記憶體
  • 外文名:Dynamic Memory Allocation
  • 類型:分配記憶體的方法
  • 特點:系統根據程式的需要即時分配
簡介,基本信息,動態分配記憶體的方法(C/C++),new可用來生成動態無名變數,malloc函式,常見的動態記憶體錯誤,

簡介

C/C++定義了4個記憶體區間:代碼區,全局變數與靜態變數區,局部變數區即棧區,動態存儲區,即堆(heap)區或自由存儲區(free store)。
堆的概念:
通常定義變數(或對象),編譯器在編譯時都可以根據該變數(或對象)的類型知道所需記憶體空間的大小,從而系統在適當的時候為他們分配確定的存儲空間。這種記憶體分配稱為靜態存儲分配;有些操作對象只在程式運行時才能確定,這樣編譯時就無法為他們預定存儲空間,只能在程式運行時,系統根據運行時的要求進行記憶體分配,這種方法稱為動態存儲分配。所有動態存儲分配都在堆區中進行。
當程式運行到需要一個動態分配的變數或對象時,必須向系統申請取得堆中的一塊所需大小的存貯空間,用於存貯該變數或對象。當不再使用該變數或對象時,也就是它的生命結束時,要顯式釋放它所占用的存貯空間,這樣系統就能對該堆空間進行再次分配,做到重複使用有限的資源。

基本信息

詳細釋義
例如我們定義一個float型數組:float score[100];
但是,在使用數組的時候,總有一個問題困擾著我們:數組應該有多大?在很多的情況下,你並不能確定要使用多大的數組,比如上例,你可能並不知道我們要定義的這個數組到底有多大,那么你就要把數組定義得足夠大。這樣,你的程式在運行時就申請了固定大小的你認為足夠大的記憶體空間。即使你知道你想利用的空間大小,但是如果因為某種特殊原因空間利用的大小有增加或者減少,你又必須重新去修改程式,擴大數組的存儲範圍。這種分配固定大小的記憶體分配方法稱之為靜態記憶體分配。但是這種記憶體分配的方法存在比較嚴重的缺陷,特別是處理某些問題時:在大多數情況下會浪費大量的記憶體空間,在少數情況下,當你定義的數組不夠大時,可能引起下標越界錯誤,甚至導致嚴重後果。
我們用動態記憶體分配就可以解決上面的問題. 所謂動態記憶體分配就是指在程式執行的過程中動態地分配或者回收存儲空間的分配記憶體的方法。動態記憶體分配不象數組等靜態記憶體分配方法那樣需要預先分配存儲空間,而是由系統根據程式的需要即時分配,且分配的大小就是程式要求的大小。
從以上動、靜態記憶體分配比較可以知道動態記憶體分配相對於靜態記憶體分配的特點:
1、不需要預先分配存儲空間
2、分配的空間可以根據程式的需要擴大或縮小。
要實現根據程式的需要動態分配存儲空間,就必須用到malloc函式.
malloc函式的原型為:void *malloc (unsigned int size) 其作用是在記憶體的動態存儲區中分配一個長度為size的連續空間。其參數是一個無符號整形數,返回值是一個指向所分配的連續存儲域的起始地址的指針。還有一點必須注意的是,當函式未能成功分配存儲空間(如記憶體不足)就會返回一個NULL指針。所以在調用該函式時應該檢測返回值是否為NULL並執行相應的操作。

動態分配記憶體的方法(C/C++)

new可用來生成動態無名變數

(1)new可用來生成動態無名變數
如 int *p=new int;
int *p=new int [10]; //動態數組的大小可以是變數或常量;而一般直接聲明數組時,數組大小必須是常量
又如:
int *p1;
double *p2;
p1=new int⑿;
p2=new double [100];
l 分別表示動態分配了用於存放整型數據的記憶體空間,將初值12寫入該記憶體空間,並將首地址值返回指針p1;
l 動態分配了具有100個雙精度實型數組元素的數組,同時將各存儲區的首地址指針返回給指針變數p2;
對於生成二維及更高維的數組,應使用多維指針
以二維指針為例
int **p=new int* [row]; //row是二維數組的行,p是指向一個指針數組的指針
for(int i=0; i<row; i++)
p[i]=new int [col]; //col是二維數組的列,p是指向一個int數組的指針
刪除這個二維數組
for(int i = 0; i < row;i++)
delete []p[i]; //先刪除二維數組的列
delete []p;
⑵使用完動態無名變數後應該及時釋放,要用到 delete 運算符
delete p; //釋放單個變數
delete [ ] p;//釋放數組變數(不論數組是幾維)
相比於一般的變數聲明,使用new和delete 運算符可方便的使用變數。

malloc函式

原型:extern void *malloc(unsigned int num_bytes);
頭檔案:在TC2.0中可以用malloc.h或 alloc.h (注意:alloc.h 與 malloc.h 的內容是完全一致的),而在Visual C++6.0中可以用malloc.h或者stdlib.h
功能:分配長度為num_bytes位元組的記憶體塊
返回值:如果分配成功則返回指向被分配記憶體的指針(此存儲區中的初始值不確定),否則返回空指針NULL。當記憶體不再使用時,應使用free()函式將記憶體塊釋放。函式返回的指針一定要適當對齊,使其可以用於任何數據對象
說明:關於該函式的原型,在舊的版本中malloc返回的是char型指針,新的ANSIC標準規定,該函式返回為void型指針,因此必要時要進行類型轉換。
名稱解釋:malloc的全稱是memory allocation,中文叫動態記憶體分配,當無法知道記憶體具體位置的時候,想要綁定真正的記憶體空間,就需要用到動態的分配記憶體。

常見的動態記憶體錯誤

使用動態記憶體分配的程式中,常常會出現很多錯誤。
1. 對NULL指針進行解引用操作
2. 對分配的記憶體進行操作時越過邊界
3. 釋放並非動態分配的記憶體
4. 試圖釋放一塊動態分配的記憶體的一部分以及一塊記憶體被釋放之後被繼續使用。
說明:
1. 動態分配最常見的錯誤就是忘記檢查所請求的記憶體是否成功分配。
2. 動態記憶體分配的第二大錯誤來源是操作記憶體時超出了分配記憶體的邊界。
3. 當你使用free時,可能出現各種不同的錯誤。
1>傳遞給free的指針必須是一個從malloc、calloc或realloc函式返回的指針。
2>傳遞給free函式一個指針,讓它釋放一塊並非動態分配的記憶體可能導致程式立即終止或在晚些時候終止。
3>試圖釋放一塊動態分配記憶體的一部分也有可能引起類似問題。
Eg:
/**
***Get 10 integers
**/
pi =malloc(10*sizeof(int ));
….
/*
**僅釋放後5個整數,前面的5個數不釋放
*/
free(pi + 5);
說明:
釋放一塊記憶體的一部分是不允許的。動態分配的記憶體必須整塊一起釋放。但是,realloc函式可以縮小一塊動態分配的記憶體,有效地釋放它尾部的部分記憶體。
4>不要訪問已經被free函式釋放了的記憶體。假定對一個指向動態分配的記憶體的指針進行了複製,而且這個指針的幾份拷貝分散於程式各處。你無法保證當你使用其中一個指針時它所指向的記憶體是不是已被另一個指針釋放。還要確保程式中所有使用這塊記憶體的地方在這塊記憶體釋放之前停止對它的使用。
5>當動態分配的記憶體不再需要使用時,應該被釋放,這樣可以被重新分配使用。分配記憶體但在使用完畢後不釋放將引起記憶體泄漏(memory leak)。
總結:
1.當數組被聲明時,必須在編譯時知道它的長度。動態記憶體分配允許程式為一個長度在運行時才知道的數組分配記憶體空間。
2.malloc和calloc函式都用於動態分配一塊記憶體,並返回一個指定該塊記憶體的指針。
1>malloc的參數就是需要分配的記憶體的位元組數。
2>calloc的參數是需要分配的元素個數和每個元素的長度。calloc函式在返回前把記憶體初始化為零。malloc函式返回時記憶體並未以任何方式進行初始化。
3>調用realloc函式可以改變一塊已經動態分配的記憶體的大小。增加記憶體塊大小有時有可能採取的方法是把原來記憶體塊上的所有數據複製到一個新的、更大的記憶體塊上。當一個動態分配的記憶體塊不再使用時,應該調用free函式把它歸還給可用記憶體池,記憶體釋放後便不能再被訪問。
3.如果請求的記憶體分配失敗,malloc、malloc和readlloc函式返回的將是一個NULL指針。
4.錯誤的訪問分配記憶體之外的區域所引起的後果類似越界訪問一個數組,但這個錯誤還能破壞可用記憶體池,導致程式失敗。
5.如果一個指針不是從早先的malloc、calloc或realloc函式返回的,它是不能作為參數傳遞給free函式的。

相關詞條

熱門詞條

聯絡我們