在學習C/C++編程的時候,老師都會反復灌輸一些概念。比如程序內變量在堆棧上的分配,棧是由高地址到低地址,堆是由低地址到高地址等等,然后畫出這樣一幅經典概念圖:
圖片來自:http://blog.csdn.net/wind19/article/details/5964137
這個概念圖容易讓讀者誤認為這一大段的程序在具體分配到的物理內存上面是連續的。換句話說,整個程序在加載到內存之后就已經固定了大小,而且程序的不同段的是緊挨着的。
而實際上,堆上面分配的內存是靈活而通常不連續的,對某個正在運行的程序而言,屬於它的堆和棧更不是緊挨着的。來一幅更細致的示意圖:
圖片來自: http://www.jianshu.com/p/aad2b27992eb
在廣闊的地址空間下面,操作系統的內核占領了高地址的空間,極低的地址空間被保留,比如NULL。
對於用戶的普通程序,則會分為5部分,如經典示意圖所示,靜態數據段(初始化和未初始化)和代碼段在最低的地址,堆和棧一低一高,向中間“生長”。
閱讀這個概念的時候很自然會問,為什么要這樣設計堆棧?
以下是我整理出的一些原因:
1. 關於相向生長,是為了充分利用堆棧的中間的區域,避免其中一方不足而另一方有大量空間,比如棧的空間不足而堆的空間有大量剩余。
2. 關於這兩個概念的設計動機,以我的經驗來聯想,在分析C++程序的時候,經常會說到函數棧。棧,代表的是程序的邏輯。堆放的是數據,只要空間足夠,數據放的位置可以很靈活。由此這兩個概念實際上區分了程序中的控制邏輯和數據。在這個框架下,程序設計與實現的討論可以非常清晰,不得不敬佩設計者的智慧。