设为首页 加入收藏

TOP

C程序内存管理
2014-11-23 19:15:07 来源: 作者: 【 】 浏览:17
Tags:程序 内存 管理

C程序的内存管理

熟悉Java语言的肯定知道,Java中内存管理是由虚拟机帮助我们完成的,在C/C++中可不是这样,程序员需要自己去分配和回收内存空间。本文记录了C程序在内存中存储结构、C变量和函数常见的存储类型、分配和回收内存等方面的内容。以下C程序所使用的编译器版本是GCC 4.4.7。

从一个C程序说起

文件的结构

对于以下这段Hello.c程序再熟悉不过了

#include
  
   

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

下面使用gcc编译它,然后运行可执行文件,再查看可执行文件的存储结构

\

可以看出,可执行文件Hello在存储时(没有调入内存时)分为代码区(text),数据区(data)和未初始化数据区(bss)3个部分。另外3个字段中,dec表示十进制总和,hex表示十六进制总和,filename表示文件名。各段的具体说明如下:

(1)代码段(text segment)< http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPqO6tOa3xUNQVda00NC1xLv6xvfWuMHuoaPNqLOjtPrC68f4yse/ydLUubLP7bXEo6i8tMHtzeK1xNa00NCzzNDyv8nS1LX308PL/KOpoaO0+sLrx/jNqLOjysfWu7bBtcSjrNLUt8DWubPM0PLS4s3itcTQ3rjEy/y1xNa4we6hozxzdHJvbmc+s6PBv8r9vt3U2rHg0uvKsdTatPrC68f4t9bF5MTatOY8L3N0cm9uZz6ho7T6wuvH+LXE1rjB7rD8wKiy2df3wuu6zbLZ1/e21M/zo6i78rbUz/O1xLXY1rfS/dPDo6mho8jnufvKx8GivLTK/aOsvs3Wsb3TsPy6rNTatPrC69bQo7vI57n7yse+1rK/yv2+3aOsvavU2tTL0NDKsbXE1bu/1bzk1tC31sXko6zIu7rz1NrS/dPDuMPK/b7dtcS12Na3o7vI57n7ysdic3PH+LrNyv2+3cf4o6zU2rT6wuvW0M2s0fnKx9L908O4w8r9vt21xLXY1rehozwvcD4KPHA+o6gyo6k8c3Ryb25nPsirvtaz9cq8u6/K/b7dx/gvvrLMrMr9vt3H+KOoaW5pdGlhbGl6ZWQgZGF0YSBzZWdtZW50L2RhdGEgc2VnbWVudKOpPC9zdHJvbmc+o6y78tXfvPKzxsr9vt22zqO6uMPH+NPysPy6rMHL1NqzzNDy1tDD98i3sbuz9cq8u6+1xMirvtax5MG/o6zS0b6ts/XKvLuvtcS+ssysseTBv6OosPzAqMirvta+ssysseTBv7rNvtayv76yzKyx5MG/o6mho9Do0qrXotLitcTKx6OsPHN0cm9uZz6xu2NvbnN0yfnD97XEseTBv7rN19a3+7Sus6PBv9TatPrC67bO1tC31sXkxNq05jwvc3Ryb25nPqGj1eK6zbvjseDT79HU1tC1xMr9vt22zrXEuMXE7srHwOAmIzIwMjg0O7XEoaM8L3A+CjxwPqOoM6OpPHN0cm9uZz7OtLP1yry7r8r9vt3H+GJzc6OoQmxvY2sgU3RhcnRlZCBCeSBTeW1ib2yjqTwvc3Ryb25nPqO6tOa0orXEysfOtLP1yry7r7XEyKu+1rHkwb+6zc60s/XKvLuvtcS+ssysseTBv6GjPHN0cm9uZz5ic3PH+NPytcTK/b7d1NqzzNDy1rTQ0Mewu+Gxu8Tausuz9cq8u6/OqjC78tXfv9XWuNXro6hOVUxMo6k8L3N0cm9uZz6jrNXius3Vu9bQtcSx5MG/yseyu82stcSjrNW71tC1xLHkwb+jqL7Wsr+x5MG/o6nI57n7w7vT0LP1yry7r77NyrnTw6Osz7XNs7vhy+a7+rfWxeTSu7j2JiMyMDU0MDu4+Mv8o6zV4srHsruwssirtcShozwvcD4KPHA+yc/K9tXi0Km2vMrHv8nWtNDQzsS8/rXEtOa0or3hubm31s72o6zG5Mq11MvQ0MqxtcTE2rTmveG5ubrN1eK49squt9bA4CYjMjAyODQ7o6zWu7K7uf224MHLttHE2rTmus3Vu8TatObH+NPyo6zU2rrzw+a74bfWzva1vaGjz8LD5s2ouf28uLj2wP3X09Hp1qTWrqGjPC9wPgo8cD67ucrH0tRIZWxsby5js8zQ8s6qwP08L3A+CjxwPjxpbWcgc3JjPQ=="https://www.cppentry.com/upload_files/article/45/1_xtiyz__.png" alt="\">

我们在Hello.c中增加了一句代码,定义一个常量i,通过分析比较,可以发现代码段text区大小增加了4个字节(一个int类型占4个字节),其他区域不变,可知常量是分配在代码段的。

在上述的基础上,在添加一句,定义一个全局变量a,并给它赋值为2,观察各区域变化

\

通过比较发现,只有数据段的大小增加了4个字节,也证明了明确被初始化的全局变量是被分配在数据区的。静态变量也是一样,可自行证之。

在上述的基础上,我们在定义一个全局变量b,但是这一个不要赋值,观察各区域变化

\

可以发现,这一次只有bss区域增加4个字节,也证明了未初始化的全局变量是分配在bss区域的。未初始化的静态变量同理,可自行证之。

进程的结构

一个程序执行的时候就表现为一个或者多个进程,其实进程内核的数据结构和上述文件的存储结构很相似,主要是多了堆内存和栈内存区域。主要的布局如下图所示


各部分说明如下:

(1)代码区(text segment):加载的是上述可执行文件的代码段,其加载到内存中的位置由加载器完成。

(2)全局初始化数据区/静态数据区(Data Segment):加载的是上述可执行文件的数据段,位置位于可执行代码段后面,可以是不相连的。在程序运行之初就为数据段申请了空间,程序退出的时候释放空间,其生命周期是整个程序的运行时期。

(3)未初始化数据区(BSS):加载的是上述可执行文件的BSS段,位置在数据段之后,可以不相连。其生命周期和数据段一样。

(4)栈区(Stack):由编译器自动分配释放,存放函数的参数值、返回值、局部变量等。在程序运行过程中动态的分配和释放,栈区位于BSS后,是向上有限扩展的。

(5)堆区(Heap):用于动态内存分配。位于栈区的后面,是向下有限扩展的。一般由程序员进行分配和释放,若不释放,在程序结束的时候,由OS负责回收。


(未完待续)






】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇ASC(1)C(树形DP) 下一篇C指针解析 ------ 指针的算术运算

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: