C语言编译后文件的结构
c语言中总体来说,编译后的程序可以分为在硬盘和在内存中运行两大种情况;每种情况下所启用的结构不一样;
1. 硬盘上:text段 data段 其他段(调试的段,动态库共享库链接表的段)
2. 内存中:text段 data段 bbs段 heap stack
注意:位于硬盘上段其大小不可变(一般情况下)
如下是一个程序在运行时的4G虚拟内存的组成:
段
-
栈用于维护函数调用的上下文,离开了栈,函数的调用就办法实现了。栈通常在用户更高的地址空间处分配,通常有数兆字节的大小。栈主要用来存放局部变量,函数调用时会在栈上有一系列的保留现场(保存上下文)及传递参数的操作。自动变量和函数调用时所需保存的信息都存放在此段中。
-
堆用来容纳应用 程序动态分配的内存区域,当程序 使用malloc或new 的时候就是得到来自堆中的内存。堆统称在栈的下方(低地址方向,但是不是紧邻的)。堆一般比栈要更大一点,一般会达到几十甚至是数百兆字节。
-
代码段(text segment):只读权限;常是指用来存放程序执行代码的一块内存区域,这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读,某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。
-
数据段(data segment):读写权限;存已被初始化了的静态数据,包含明确的初始化值,保存在硬盘上,由.exec读取。数据段通常是指用来存放程序中 已初始化的全局变量或者静态变量 的一块内存区域。
-
BSS 段(Block Started by Symbol ):未初始化的数据段,不保存在硬盘上,只是记录数据所需空间的大小,程序开始执行之前,由内核进行初始化为0。
-
常量数据段(.rodata):ro表示read only,用于 存放不可变修改的常量数据 ,一旦程序中对其修改将会出现段错误
(1) 程序中的常量不一定就放在rodata中,有的立即数和指令编码放在.text中
(2)对于字符串常量,若程序中存在重复的字符串,编译器会保证只存在一个,一般声明形式为const char * xxx
(3)rodata是在多个进程间共享的 -
文件映射区域 :如动态库、共享内存等映射物理空间的内存,一般是 mmap 函数所分配的虚拟地址空间。
全局、局部、静态全局、静态局部变量
全局变量、静态全局变量和静态局部变量都存放在内存的静态存储区域,局部变量存放在内存的栈区
-
全局变量 关键字:global:整个工程 内都可以访问,只能定义一次。是静态存储方式,存储在 静态存储区,全局变量只需在一个源文件中定义,任意文件的任意函数都可以修改全局变量 。如果全局变量定义在源文件a中,其他文件想要使用这个全局变量,需要用extern声明一下。
如果一个C程序包括两个文件,在两个文件中都需要用到同一个外部变量NUM,此时不能分别在两个文件中各自定义一个外部变量NUM,否则在进行程序链接是会出现 重复定义的错误;正确的做法是:在任一文件中定义全局变量NUM,而在另一文件中用 extern 对NUM 作 “外部变量声明”,即 extern NUM;这样在编译和链接时,系统就会知道NUM有 外部链接,可以从别处找到已定义的NUM,然后将NUM的作用域进行扩展 -
局部变量:局部区域内有用,位于栈上。
-
静态static的含义