複製鏈接
請複製以下鏈接發送給好友

動態分配內存

鎖定
所謂動態內存分配(Dynamic Memory Allocation)就是指在程序執行的過程中動態地分配或者回收存儲空間的分配內存的方法。動態內存分配不象數組靜態內存分配方法那樣需要預先分配存儲空間,而是由系統根據程序的需要即時分配,且分配的大小就是程序要求的大小。
中文名
動態分配內存
外文名
Dynamic Memory Allocation
類    型
分配內存的方法
特    點
系統根據程序的需要即時分配

動態分配內存簡介

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

動態分配內存基本信息

詳細釋義
例如我們定義一個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,中文叫動態內存分配,當無法知道內存具體位置的時候,想要綁定真正的內存空間,就需要用到動態的分配內存。

動態分配內存常見的動態內存錯誤

使用動態內存分配的程序中,常常會出現很多錯誤。 [2] 
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函數的。 [2] 
參考資料