堆 and 棧

一、預備知識—程序的內存分配

一個由c/C++編譯的程序佔用的內存分爲以下幾個部分

1、棧區(stack)— 由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似於數據結構中的棧。

2、堆區(heap) — 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。注意它與數據結構中的堆是兩回事,分配方式倒是類似於鏈表,呵呵。

3、全局區(靜態區)(static)

4、文字常量區—常量字符串就是放在這裏的。 程序結束後由系統釋放

5、程序代碼區—存放函數體的二進制代碼。


二、示例如下:

#include "stdio.h"
#include "string.h"
#include "malloc.h"

int variable = 0; //全局初始化區
char* p1;	//全局未初始化區

int main(char argc,char** argv) 
{ 
	int b = 0;			//棧 
	char s[] = "abc";	//棧 
	char *p2;			//棧 
	char *p3 = "123456"; //123456/0在常量區,p3在棧上,且指針內容不可修改。 
	static int c =0; //全局(靜態)初始化區 
	p1 = (char *)malloc(10);	//分配得來得10和20字節的區域就在堆區。  
	p2 = (char *)malloc(20);	//動態分配得來的內存是不連續的
	
	strcpy(p1, "123456"); //123456/0放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一個地方。
	
	return 0; 
}
三、堆和棧的申請

1、棧:當前系統中沒有使用的棧空間大於申請的棧大小,就可以正常分配棧。否則,會報異常,提示棧溢出。

2、堆:其是操作系統用鏈表管理的空閒內存。從此可以看出,動態申請的堆空間是不連續的。當申請堆空間時,操作系統會遍歷前面的鏈表,找到一個空間大於所申請的堆節點,然後將該節點賦予申請內存的指針變量,同時,將該堆節點從空閒鏈表中刪除。同時,在大多數的操作系統中,當動態申請內存的時候,會將申請的空間大小記錄在該塊內存的首地址。這樣delete才知道要釋放多大的內存。也就是爲什麼我們可以這樣釋放申請的內存:delete [] p ;


四、堆和棧中的東東

堆:一般來說是在堆的第一個字節中存放該堆的大小,其他空間由程序員隨意發揮。

棧:入棧的動作發生在調用函數開始時,出棧發生在調用函數完成時,需要恢復調用之前的“現場”。所以,在調用函數時,第一個進棧的是主函數中,被調用函數後的第一條可執行語句。然後是主函數的各個參數,在大多數C編譯器中,參數的入棧順序是:從右到左。然後是主函數中的局部變量。注意,靜態變量是不入棧的。因爲靜態變量在全局區,所以沒有必要。

在本次調用完成後,需要出棧。請注意出棧的順序:和入棧剛好相反,是先進後出,即FILO。詳細是:主函數的局部變量,主函數的參數,最後是被調用函數下一條可執行語句。程序從此處開始執行。


先寫到這裏,更深入的內容,等需要用的時候,在細細整理。


發佈了6 篇原創文章 · 獲贊 0 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章