圖一、內存四區模型
流程說明
一、操做系統把物理硬盤代碼load到內存
二、操做系統把c代碼分紅四個區
三、操做系統找到main函數入口執行程序員
一個由c/C++編譯的程序佔用的內存分爲如下幾個部分
一、棧區(stack):由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操做方數據結構
式相似於數據結構中的棧。
二、堆區(heap: 通常由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回 收 。函數
注意它與數據結構中的堆是兩回事,分配方式卻是相似於鏈表。spa
三、數據區:主要包括靜態全局區和常量區,若是要站在彙編角度細分的話還能夠分爲不少小的區。
全局區(靜態區)(static):全局變量和靜態變量的存儲是放在一塊的,初始化的全局變操作系統
量和靜態變量在一塊區域, 未初始化的全局變量和未初始化的靜態變量在相鄰的另外一塊區域。 .net
程序結束後有系統釋放
常量區 :常量字符串就是放在這裏的。 程序結束後由系統釋放指針
四、代碼區:存放函數體的二進制代碼。blog
一、堆棧的生長方向和存放數據增加方向不同生命週期
圖二、堆棧的生長方向內存
變量三要素是:名稱、大小、做用域。那麼變量的生命週期是多長呢?
編譯器是如何管理每一個函數間變量的生命週期呢?
要研究變量的生命週期,而變量通常又是在函數中定義分配空間的。
所以下面研究一下變量做爲函數參數和返回值傳遞分析
下面咱們具體總結一下,各個函數的變量的生命週期
main裏面的變量分配內存,函數fa(),函數fb()中的變量分配的內存空間它們的生命週期都是多長呢?
上述圖1,已經說明了內存主要分爲四區,所以每一個函數中變量在堆棧的生命週期是不一樣的,
同時在函數調用的時候,先執行的函數最後才執行完畢
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");
}
總結:
一、主調函數分配的內存空間(堆,棧,全局區)能夠在被調用函數中使用,能夠以指針做函數參數的形式來使用
二、被調用函數分配的內存空間只有堆區和全局區能夠在主調函數中使用(返回值和函數參數),而棧區卻不行,由於棧區函數體運行完以後
這個函數佔用的內存編譯器自動幫你釋放了。
三、必定要明白函數的主被調關係以及主被調函數內存分配回收,也就是後面接下幾篇總結的函數的輸入輸出內存模型