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

堆內存

鎖定
堆內存是區別於棧區、全局數據區和代碼區的另一個內存區域。堆允許程序在運行時動態地申請某個大小的內存空間
中文名
堆內存
外文名
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(長度),(數據類型*)表示指針.

堆內存內存方式

例:
int *p;
p = (int*)malloc(sizeof(int));
使用malloc函數分配內存時,返回值要經過類型轉換才可賦予一個指針變量。該函數如分配內存成功,則返回其始地址,否則返回NULL。頭文件為#include<stdlib.h>。
例:
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;
}