堆記憶體(記憶體區域)

Heap(數據結構)一般指本詞條

本詞條是多義詞,共2個義項
更多義項 ▼ 收起列表 ▲

堆記憶體是區別於棧區、全局數據區和代碼區的另一個記憶體區域。堆允許程式在運行時動態地申請某個大小的記憶體空間

基本介紹

  • 中文名:堆記憶體
  • 外文名:heap
  • 區別:於棧區
  • 類型軟體
  • 獲得堆記憶體:malloc()
比較,分配,重要函式,記憶體方式,典型示例,

比較

在學習C程式設計語言時,會遇到兩個很相似的術語:堆記憶體和棧記憶體。這兩個術語雖然只有一字之差,但是所表達的意義還是有差別的,堆記憶體和棧記憶體的區別可以用如下的比喻來看出:使用堆記憶體就象是自己動手做喜歡吃的菜餚,比較麻煩,但是比較符合自己的口味,而且自由度大。使用棧記憶體就象我們去飯館裡吃飯,只管點菜(發出申請)、付錢和吃(使用),吃飽了就走,不必理會切菜、洗菜等準備工作和洗碗、刷鍋等掃尾工作,他的好處是快捷,但是自由度小。作業系統中所說的堆記憶體和棧記憶體,在操作上有上述的特點,這裡的堆記憶體實際上指的就是(滿足堆記憶體性質的)優先佇列的一種數據結構,第1個元素有最高的優先權;棧記憶體實際上就是滿足先進後出的性質的數學或數據結構。
堆記憶體
堆記憶體和棧記憶體

分配

在標準C語言上,使用malloc等記憶體分配函式獲取記憶體即是從堆中分配記憶體,而在一個函式體中例如定義一個數組之類的操作是從棧中分配記憶體。從堆中分配的記憶體需要程式設計師手動釋放,如果不釋放,而系統記憶體管理器又不自動回收這些堆記憶體的話(實現這一項功能的系統很少),那就一直被占用。如果一直申請堆記憶體,而不釋放,記憶體會越來越少,很明顯的結果是系統變慢或者申請不到新的堆記憶體。而過度的申請堆記憶體(可以試試在函式中申請一個1G的數組!),會導致堆被壓爆,結果是災難性的。
堆記憶體
動態分配堆記憶體
我們掌握堆記憶體的權柄就是返回的指針,一旦丟掉了指針,便無法在我們視野內釋放它。這便是記憶體泄露。而如果在函式中申請一個數組,在函式體外調用使用這塊堆記憶體,結果將無法預測。 我們知道在c/c++ 中定義的數組大小必需要事先定義好,他們通常是分配在靜態記憶體空間或者是在棧記憶體空間內的,但是在實際工作中,我們有時候卻需要動態的為數組分配大小,這時就要用到堆記憶體分配的概念。在堆記憶體分配時首先應該知道作業系統有一個記錄空閒記憶體地址的鍊表,當系統收到程式的申請時,會遍歷該鍊表,尋找第一個空間大於所申請空間的堆結點,然後將該結點從空閒結點鍊表中刪除,並將該結點的空間分配給程式,另外,對於大多數系統,會在這塊記憶體空間中的首地址處記錄本次分配的大小,這樣,代碼中的delete語句才能正確的釋放本記憶體空間。另外,由於找到的堆結點的大小不一定正好等於申請的大小,系統會自動的將多餘的那部分重新放入空閒鍊表中。堆記憶體是向高地址擴展的數據結構,是不連續的記憶體區域。這是由於系統是用鍊表來存儲的空閒記憶體地址的,自然是不連續的,而鍊表的遍歷方向是由低地址向高地址。堆記憶體的大小受限於計算機系統中有效的虛擬記憶體。由此可見,堆記憶體獲得的空間比較靈活,也比較大。堆記憶體是由new分配的記憶體,一般速度比較慢,而且容易產生記憶體碎片,不過用起來最方便.另外,在WINDOWS下,最好的方式是用VirtualAlloc分配記憶體,它直接在進程的地址空間中保留一塊記憶體,雖然用起來最不方便。但是速度快,也最靈活。

重要函式

獲得堆記憶體:malloc()
動態分配堆記憶體
原型:extern void *malloc( unsigned int num_bytes);
功能:分配長度為num_bytes位元組的記憶體塊
說明:如果分配成功則返回指向被分配記憶體的指針,否則返回空指針NULL。當記憶體不再使用時,應使用free()函式將記憶體塊釋放。
malloc的語法是:指針名=(數據類型*)malloc(長度),(數據類型*)表示指針.

記憶體方式

malloc函式
例:
int *p;
p = (int*)malloc(sizeof(int));
使用malloc函式分配記憶體時,返回值要經過類型轉換才可賦予一個指針變數。該函式如分配記憶體成功,則返回其始地址,否則返回NULL。頭檔案為#include<stdlib.h>。
new運算符
例:
int *p,*q;
p = new int;//申請分配一個int型記憶體空間
p = new int(10);//申請一個int型空間存放10
q = new int[10];//申請分配10個int型的記憶體空間
new分配記憶體時不需要類型轉換。用new申請的空間必須要用delete釋放。而且指針值不能改變。形式有:delete指針變數名(可釋放一個記憶體單元)、delete[]指針變數名(可釋放若干個記憶體單元)。

典型示例

例1:
#include<iostream>
using namespace std;
main()
{
int array_size;//元素個數
int *array;//用於動態開闢數組的指針變數
cin>>array_size;
array=(int*)malloc(array_size*sizeof(int));/*利用malloc在堆記憶體中開闢記憶體空間,它的大小是元素的個數乘以該數據類型的長度 */
for(int i=0;i<array_size;i++)
array[i]=i;//輸入數組
for( i=0;i<array_size;i++)
cout<<array[i]<<",";//以逗號間距輸出數組
cout<<endl;//換行
free(array);//利用free釋放動態開闢的堆記憶體空間
cin.get();//按任意鍵結束
return 1;//返回值
}//////////////VC6.0通過 網頁格式符 請不要直接複製貼上本段編譯
這裡要特別注意個地方就是:
array=(int*)malloc(array_size*sizeof(int));malloc()
函式原形本身是void*malloc(size_tsize),由於動態分配空間計算機並不知道是用來做什麼的所以是無類型的,但你要把它用在動態的整形數組上的時候就要顯式的轉換成int*了。
例2:
//malloc.c
#include "iostream"
using namespace std;
main()
{
char *p;
p=(char*)malloc(100*sizeof(char));
if(p)
printf("Memory Allocated at:%x \n",p);
else
printf("Not Enough Memory Available! \n");
free(p);
getchar();//按任意鍵結束
return 0;
}

相關詞條

熱門詞條

聯絡我們