程序內存佈局是理解軟件本質的基礎要素。支持一個程序運行的所有內存大體可分爲以下幾部分,或者說程序運行需要系統爲其提供如下幾部分存儲區域:
棧:由編譯器自動分配釋放,存放函數參數,局部變量等,特點爲後進先出。
堆:程序員調用malloc/free進行內存動態分配和釋放所操作的內存區域。
全局數據區(靜態區):全局變量以及static變量存放的內存區,注意static變量不管在哪裏定義都存放在全局數據區(見C基礎static篇)。初始化的全局和靜態變量在全局初始化區,未初始化的全局和靜態變量在全局未初始化區。整個全局數據區在程序結束後由系統釋放。
程序代碼區:存放二進制的程序代碼,一般規定爲只讀。
常量區:裏面存放常量,不能修改,如"adgf"這樣的字符串就存放在常量區,一直佔用到程序結束。
不同編譯器和系統的內存佈局劃分會有細小差別,但上述幾大塊基本跑不掉。它們是組成一個完整程序的內存基礎,這裏的程序指運行在沒有OS的裸系統上的控制程序,比如單片機應用等,而引入OS後,單個進程所包含的元素也基本歸於以上幾類。下面舉例說明C程序中不同元素在內存中的定位區域:
int a = 0; //全局初始化區
char *p1; //全局未初始化區
void main()
{
int b; //棧
char s[] = "abc"; //s[]在棧上,abc在常量區
char *p2; //棧
char *p3 = "12345"; // p3在棧上,12345在常量區。
static int c =0; //全局(靜態)初始化區
p1 = (char *)malloc(10);
p2 = (char *)malloc(20); //分配的10和20字節內存塊在堆裏,而p1,p2本身在棧中
strcpy(p1,"12345"); //12345在常量區,編譯器會將它與p3所指的"12345"優化成一塊
}
總結:函數體中定義的局部變量(非static)位於棧上;通過malloc,calloc等函數分配所得到的內存在堆上;所有全局變量以及static靜態變量都放在全局數據區。程序自身指令位於只讀代碼區。常量位於常量區(有的也散列在代碼區,因爲都是隻讀屬性,可以合併放在一起)。