圖一:內存四區模型
流程說明
1、操作系統把物理硬盤代碼load到內存
2、操作系統把c代碼分成四個區
3、操作系統找到main函數入口執行
一:內存四區
一個由c/C++編譯的程序佔用的內存分爲以下幾個部分
1、棧區(stack):由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似於數據結構中的棧。
2、堆區(heap: 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回 收 。注意它與數據結構中的堆是兩回事,分配方式倒是類似於鏈表。
3、數據區:主要包括靜態全局區和常量區,如果要站在彙編角度細分的話還可以分爲很多小的區。
全局區(靜態區)(static):全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區 域, 未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域。 程序結束後有系統釋放
常量區 :常量字符串就是放在這裏的。 程序結束後由系統釋放
4、代碼區:存放函數體的二進制代碼。
二:相關代碼解讀
char*fa()
{
char*pa = "123456";//pa指針在棧區,“123456”在常量區,該函數調用完後指針變量pa就被釋放了
char*p = NULL; //指針變量p在棧中分配4字節
p=(char*)malloc(100);//本函數在這裏開闢了一塊堆區的內存空間,並把地址賦值給p
strcpy(p, "wudunxiong 1234566");//把常量區的字符串拷貝到堆區
return p;//返回給主調函數fb(),相對fa來說fb是主調函數,相對main來說,fa(),fb()都是被調用函數
}
char*fb()
{
char*pstr = NULL;
pstr = fa();
return pstr;//指針變量pstr在這就結束
}
void main()
{
char*str = NULL;
str = fb();
printf("str = %s\n",str);
free(str); //防止內存泄露,被調函數fa()分配的內存存的值通過返回值傳給主調函數,然後主調函數釋放內存
str = NULL;//防止產生野指針
system("pause");
}
三:總結
1、主調函數分配的內存空間(堆,棧,全局區)可以在被調用函數中使用,可以以指針作函數參數的形式來使用
2、被調用函數分配的內存空間只有堆區和全局區可以在主調函數中使用(返回值和函數參數),而棧區卻不行,因爲棧區函數體運行完之後
這個函數佔用的內存編譯器自動幫你釋放了。
3、一定要明白函數的主被調關係以及主被調函數內存分配回收,也就是後面接下幾篇總結的函數的輸入輸出內存模型。
4、sizeof測量的就是在棧區和堆區的字長,比如講,在一個結構體中,存在一個 static int a 的成員,sizeof是不會計算a的這四個字節長度,因爲static靜態數據成員是在數據區內,不在sizeof的測量範圍內。