歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> C程序內存管理

C程序內存管理

日期:2017/3/1 9:35:22   编辑:Linux編程

C程序的內存管理

熟悉Java語言的肯定知道,Java中內存管理是由虛擬機幫助我們完成的,在C/C++中可不是這樣,程序員需要自己去分配和回收內存空間。本文記錄了C程序可執行文件的存儲結構、在內存中的存儲結構等方面的內容。以下C程序所使用的編譯器版本是GCC 4.4.7。

從一個C程序說起

文件的結構

對於以下這段Hello.c程序再熟悉不過了

#include<stdio.h>

int main(void)
{
printf("Hello World\n");
return 0;
}

下面使用gcc編譯它,然後運行可執行文件,再查看可執行文件的存儲結構

可以看出,可執行文件Hello在存儲時(沒有調入內存時)分為代碼區(text),數據區(data)和未初始化數據區(bss)3個部分。另外3個字段中,dec表示十進制總和,hex表示十六進制總和,filename表示文件名。各段的具體說明如下:

(1)代碼段(text segment):存放CPU執行的機器指令。通常代碼區是可以共享的(即另外的執行程序可以調用它)。代碼區通常是只讀的,以防止程序意外的修改它的指令。常量數據在編譯時在代碼區分配內存。代碼區的指令包括操作碼和操作對象(或對象的地址引用)。如果是立即數,就直接包含在代碼中;如果是局部數據,將在運行時的棧空間中分配,然後在引用該數據的地址;如果是bss區和數據區,在代碼中同樣是引用該數據的地址。

(2)全局初始化數據區/靜態數據區(initialized data segment/data segment),或者簡稱數據段:該區域包含了在程序中明確被初始化的全局變量,已經初始化的靜態變量(包括全局靜態變量和局部靜態變量)。需要注意的是,被const聲明的變量和字符串常量在代碼段中分配內存。這和匯編語言中的數據段的概念是類似的。

(3)未初始化數據區bss(Block Started By Symbol):存儲的是未初始化的全局變量和未初始化的靜態變量。bss區域的數據在程序執行前會被內核初始化為0或者空指針(NULL),這和棧中的變量是不同的,棧中的變量(局部變量)如果沒有初始化就使用,系統會隨機分配一個值給它,這是不安全的。

上述這些都是可執行文件的存儲結構分析,其實運行時的內存結構和這個十分類似,只不過多了堆內存和棧內存區域,在後面會分析到。下面通過幾個例子驗證之。

還是以Hello.c程序為例

我們在Hello.c中增加了一句代碼,定義一個常量i,通過分析比較,可以發現代碼段text區大小增加了4個字節(一個int類型占4個字節),其他區域不變,可知常量是分配在代碼段的。

在上述的基礎上,在添加一句,定義一個全局變量a,並給它賦值為2,觀察各區域變化

通過比較發現,只有數據段的大小增加了4個字節,也證明了明確被初始化的全局變量是被分配在數據區的。靜態變量也是一樣,可自行證之。

在上述的基礎上,我們在定義一個全局變量b,但是這一個不要賦值,觀察各區域變化

可以發現,這一次只有bss區域增加4個字節,也證明了未初始化的全局變量是分配在bss區域的。未初始化的靜態變量同理,可自行證之。

C++ 隱式類類型轉化 Implicit Class-Type Conversions http://www.linuxidc.com/Linux/2013-01/78071.htm

C語言變長數組之剖析 http://www.linuxidc.com/Linux/2013-07/86997.htm

C語言需要注意的問題 http://www.linuxidc.com/Linux/2013-05/84301.htm

C語言位域的使用及其注意點 http://www.linuxidc.com/Linux/2013-07/87027.htm

C語言中簡單的for循環和浮點型變量 http://www.linuxidc.com/Linux/2013-08/88514.htm

更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2015-01/111157p2.htm

Copyright © Linux教程網 All Rights Reserved