操作系統棧和堆
地址空間布局:

棧:
執行期間編譯器自動分配,編譯器用它實現函數調用,調用函數時,棧增長,函數返回時,棧收縮。局部變量、函數參數、返回數據、返回地址等放在棧中
棧的特點
- 內存分配取決於編譯器,用戶棧在程序運行期間可以動態的擴展和收縮。
- 和數據結構中的“棧”本質上是不一樣的,但是操作方式類似於棧。
- 數據從棧中的進出滿足“后進先出”的規律。
- 棧向低地址方向增長,esp(棧指針)指向棧頂元素。
堆:
動態儲存器分配器維護着的一個進程的虛擬存儲器區域。一般由程序員分配釋放(堆在操作系統對進程初始化的時候分配),若程序員不釋放,程序結束時可能由OS回收,每個進程,內核都維護着一個變量brk指向堆頂。
堆的特點
- 內存分配取決於程序員,C/C++可以手動釋放該片內存。
- 和數據結構的”堆“完全兩回事,沒有半點關系,在這里堆的結構更像鏈表。
- 所有的對象,包括數組的對象都存在堆上。
- 堆內存被所有的線程共享。
- 引用類型總是放在堆中。
- 堆向高地址方向增長,內核都維護的變量brk指向堆頂。
注意:值類型和指針總是放在他們被聲明的地方(復雜)
當值類型的數據在方法體內被聲明時,它們都應該放在棧上。
如果一個只類型被聲明在方法體外且存在於一個引用類型中,那么它將會被堆里的引用類型所取代。
全局區/靜態區:
全局變量、靜態變量、常量的存儲區域,程序終止時系統釋放。
文字常量區:
存放常量字符串,程序結束后由系統釋放。
程序代碼區:
存放函數體(類成員函數和全局函數)的二進制代碼。
實例
int a = 0; //全局初始化區
char *p1; //全局未初始化區
void main()
{
int b; //棧
char s[] = "123"; //棧
char *p2; //棧
char *p3 = "sdfghhj"; //其中,“sdfghhj\0”常量區,p3在棧區
static int c = 0; //全局區
p1 = (char*)malloc(10); //10個字節區域在堆區
strcpy(p1,"sdfghhj"); //"sdfghhj\0"在常量區,編譯器可能會優化p1和p3指向同一塊區域
}
棧和堆的區別:
- 棧內存存儲的的是局部變量,堆內存存儲的是實體。
- 棧內存的更新的速度會更快些(局部變量),堆內存的更新速度相對更慢。
- 棧內存的訪問直接從地址讀取數據到寄存器,然后放到目標地址,而堆內存的訪問更麻煩,先將分配的地址放到寄存器,在讀取地址的值,最后再放到目標文件中,開銷更大。
- 棧內存是連續的空間,堆內存一般情況不是連續的,頻繁地開辟空間,釋放空間容易產生內存碎片(外碎片)。
棧和堆的聯系:
堆中對象是直接由棧中的句柄(引用)管理者,所以堆負責產生真實對象,棧負責管理對象。
