C/C++ 內存分配知識

C語言中內存分爲五個區
棧(stack):用來存放函數的形參和函數內的局部變量。由編譯器分配空間,在函數執行完後由編譯器自動釋放。
堆(heap):用來存放由動態分配函數(如malloc)分配的空間。是由程序員自己手動分配的,並且必須由程序員使用free釋放。如果忘記用free釋放,會導致所分配的空間一直佔着不放,導致內存泄露。
全局區/靜態區:用來存放全局變量和靜態變量。程序結束時由系統釋放,分爲全局初始化區和全局未初始化區;存在於程序的整個運行期間,是由編譯器分配和釋放的。
文字常量區:常量字符串放於此,程序結束時由系統釋放。例如char *c = “123456”;則”123456”爲文字常量,存放於文字常量區。也由編譯器控制分配和釋放。
程序代碼區:用來存放程序的二進制代碼。

下面通過幾個例子來看一下,具體C程序中的內存分配吧:

/* 例1 main1.c */
int a = 0; //全局初始化區
char *p1; //全局未初始化區
void main()
{
int b; //棧
char s[] = “abc”; //s在棧,"abc\0"在文字常量區
char *p2; //棧
char *p3 = “123456”; //"123456\0"在常量區,p3在棧上
static int c =0; //全局區
p1 = (char *)malloc(10); //p1在棧,分配的10字節在堆
p2 = (char *)malloc(20); //p2在棧,分配的20字節在堆
strcpy(p1, “123456”); //"123456"放在常量區,編譯器可能會優化爲和p3的指向同一塊區域
}


/* 例2 main2.c */
//返回char型指針
char *f()
{
//s數組存放於棧上
char s[4] = {'1','2','3','0'};
return s; //返回s數組的地址,但程序運行完s數組就被釋放了
}
void main()
{
char *s;
s = f();
printf (%s, s); //打印出來亂碼。因爲s所指向地址已經沒有數據
}


C++五大內存分區

在C++中,內存分成5個區,他們分別是堆、棧、自由存儲區、全局/靜態存儲區和常量存儲區。

棧,就是那些由編譯器在需要的時候分配,在不需要的時候自動清楚的變量的存儲區。裏面的變量通常是局部變量、函數參數等。

堆,就是那些由new分配的內存塊,他們的釋放編譯器不去管,由我們的應用程序去控制,一般一個new就要對應一個delete。如果程序員沒有釋放掉,那麼在程序結束後,操作系統會自動回收。

自由存儲區,就是那些由malloc等分配的內存塊,他和堆是十分相似的,不過它是用free來結束自己的生命的。

全局/靜態存儲區,全局變量和靜態變量被分配到同一塊內存中,在以前的C語言中,全局變量又分爲初始化的和未初始化的,在C++裏面沒有這個區分了,他們共同佔用同一塊內存區。

常量存儲區,這是一塊比較特殊的存儲區,他們裏面存放的是常量,不允許修改(當然,你要通過非正當手段也可以修改,而且方法很多)


《Unix環境高級編程》(著名的APUE)中提出:
C程序的內存佈局:Text,Data,BSS,Stack, Heap.
Text是程序的代碼段
Data是程序中初始化了的全局、靜態數據變量。
BSS是程序中未初始化的全局、靜態數據變量。即使全局、靜態數據變量初始化爲0仍然是屬於BSS段。(未初始化的數據段
Stack是程序中的局部變量,由高地址到低地址向下增長。
Heap是malloc調用動態分配的內存,由低地址到高地址向上增長。

根據網上別人的觀點結合自己的測試,得出的結論:
1、 經過初始化的全局變量和靜態變量保存在數據段中。
2、 未經初始化的全局變量和靜態變量保存在BSS段。
3、 函數內部聲明的局部變量保存在堆棧段(棧)中,函數調用相關信息也在棧中。
4、 const修飾的全局變量保存在文本段中,const修飾的局部變量保存在堆棧段中。
5、 字符串常量保存在文本段中。

查看各段的大小用size命令:size test.out (test.out爲編譯連接後的可執行文件),可以查看到text、data、bss段的大小。

對C內存的深入研究(根據《C專家編程》)以及實例和結論,一篇很好的文章,見:
http://blog.csdn.net/chgaowei/archive/2010/03/03/5340796.aspx

http://www.51testing.com/html/38/225738-220959.html

發佈了13 篇原創文章 · 獲贊 5 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章