读书人

C语言内存储器布局

发布时间: 2013-07-16 22:38:04 作者: rapoo

C语言内存布局
C语言从源程序文件(.c)到二进制程序文件(.exe或者.dll),需要经过三个阶段,编译->汇编->链接。编译阶段,将源程序文件编译成汇编代码。在由汇编程序,执行汇编代码,对应每个源程序文件生成一个目标文件(.obj)。最后通过链接将各个目标文件链接生成最后的可执行文件。在C语言中有六种数据段,可以分为两类:一类是静态生成的,类是动态生成的。不同的数据段,会在不同的阶段生成。下面首先介绍下这六种数据段的概念。
代码段(Code)
由各个源程序的函数对应的机器代码组成,比如顺序代码(加、减、与等运算符),选择代码(if、if…else等选择运算符),循环代码(while等)。由源程序生成的目标文件中保存了函数对应的代码段。

只读数据段(RO Data)
在程序中定义的不可改变的常量数据(const关键字修饰)。比如全局常量、局部常量、在程序中使用的常量。这部分数据段也保存在编译后生成的目标文件中。

读写数据段(RW Data)
在程序中定义的可读可写的并且已经初始化的数据。例如已初始化的全局变量、局部静态变量。这部分数据保存在编译后生成的目标文件中。

未初始化数据段(BSS)
和读写段类似,属于静态数据。和读写数据段的区别是它没有经过初始化。因为没有经过初始化,所在不占用目标文件的大小,只是在目标文件中标示该数据段的大小。只在程序初始化时产生。

堆区
由malloc、calloc、realloc等分配内存的函数分配的堆内存。它在程序执行时,动态生成的内存。这部分内存很自由,由程序控制生成和释放。同时也很危险,很容易造成内存泄露,内存不足等错误。

栈区
和堆区一样会在程序执行时动态生成。与堆不同的是,栈的生成和释放都是系统自动进行。所以相对来说很安全并且效率很高。栈中保存了函数的参数,函数中定义的变量(静态变量除外),以及函数返回值。每个函数对应一个栈帧,栈帧按照先进后出的顺序来释放空间。

在理解上面六种数据段后,我们在看各个数据段都在C语言哪些阶段产生。程序在通过编译汇编后,由C源程序文件生成对应的目标文件,目标文件中保存了每个函数的代码段,以及源程序文件中定义的只读数据段和读写数据段。未初始化数据段、堆和栈不会再这个阶段产生。在链接时,Link命令将所有的目标文件中的代码段、只读数据段和读写数据段进行抽出和重组。重新组合而成一个新的二进制文件。这个二进制文件就是可执行文件,它也是由程序段、只读数据段和读写数据段组合而成。未初始化数据段、堆和栈在这个阶段也还没有产生。当可执行文件进行初始化时,会产生未初始化数据段。在执行阶段产生堆和栈内存。这个就是C语言从编译到执行时内存的分配过程。

读书人网 >C语言

热点推荐