基本上程序员在开始接触Linux编程时就大抵就都听过代码段、数据段等等概念,它们是各种数据存放的位置。通过objdump -h命令可以查看一个.o文件(已编译成二进制文件但未链接)的各个段:
1. 代码段(.txt)
.txt段存放代码(如函数)与部分整数常量,.txt段的数据可以被执行
2. 数据段(.data)
.data用于存放初始化过的全局变量。若全局变量值为0,为了优化编译器会将它放在.bss段中
3. bss段(.bss)
.bss段被用来存放那些没有初始化或者初始化为0的全局变量。bss段只占运行时的内存空间而不占文件空间。在程序运行的整个周期内,.bss段的数据一直存在
.data和.bss段的区别可以通过下面程序验证:
#include <stdio.h>
char global_arr[1024 * 1024]; //存放在.bss段
int main(void)
{
return 0;
}
编译后查看大小:
显然,global_arr数组占据的1M空间并没有占据文件空间。将global_arr数组改放在.data段中:
char global_arr[1024 * 1024] = {4}; //存放在.data段
编译后查看大小:
文件变成了1M多,显然.data段上的数据是占据文件空间的。
4. 常量数据段(.rodata)
ro表read only,用于存放不可变修改的常量数据,一旦程序中对其修改将会出现段错误:
(1) 程序中的常量不一定就放在rodata中,有的立即数和指令编码放在.text中
(2) 对于字符串常量,若程序中存在重复的字符串,编译器会保证只存在一个
(3) rodata是在多个进程间共享的
(4) 有的嵌入式系统,rodata放在ROM(或者NOR FLASH)中,运行时直接读取无需加载至RAM( 哈佛和冯诺依曼,从STM32的const全局变量说起有所记录)
想要将数据放在.rodata只需要加上const属性修饰即可。
5. 栈
栈是用于存放临时变量和函数调用的。栈也是一种先进后出的数据结构,函数的递归调用正得益于栈的存在。需注意存在栈的数据只在当前函数和子函数中有效,一旦函数返回数据将会被自动释放。
6. 堆
堆的使用周期有使用者控制,程序中的内存泄漏多因程序员对堆的管理不当引起,需谨慎。
7. .comment段
在上图中还看到.comment段,它存放的是编译器版本等信息。除了.comment,还有.note、.hash等其他段,了解即可。