目录
- .bss段
- .data段
- .rodata段
- .text段
- 实例
简介
为了更好的调试程序,需要对程序编译后产生的库或可执行程序有一定的了解,本文主要介绍一下其中的段信息
.bss段
BSS段(bss segment)通常是指用来存放程序中未初始化的或者初始化为0的全局变量和局部静态变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。
默认初始化为0的全局变量,它不占用程序文件的大小,但是占用程序运行时的内存空间,可自行在程序中定义全局数组,查看初始化和不初始化编译出的文件大小。
.data段
数据段(data segment)通常是指用来存放程序中已初始化的全局变量和局部静态变量的一块内存区域,初始化为0的变量出于编译优化的策略还是被保存在BSS段。数据段属于静态内存分配。
.rodata段
该段也叫常量区,用于存放常量数据,ro就是Read Only之意
但是注意并不是所有的常量都是放在常量数据段的,其特殊情况如下:
- 有些立即数与指令编译在一起直接放在代码段。
- 对于字符串常量,编译器会去掉重复的常量,让程序的每个字符串常量只有一份。
- 有些系统中rodata段是多个进程共享的,目的是为了提高空间的利用率
.text段
text段是用于存放程序代码的,编译时确定,只读。
更进一步讲是存放处理器的机器指令,当各个源文件单独编译之后生成目标文件,经连接器链接各个目标文件并解决各个源文件之间函数的引用,
与此同时,还得将所有目标文件中的.text段合在一起,但不是简单的将它们“堆”在一起就完事,还需要处理各个段之间的函数引用问题。
这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。
.dynstr段
该段存放调用动态库信息和调用的相关函数
编译程序时,若需要链接动态库,需要加入-l库名称和-L 库路径,其实此时去找的是动态库的符号等信息,编译到自己的程序里,等到运行时,会搜索LD_LIBRARY_PATH去寻找库的本身内容
显示加载和隐式加载的区别在于,显示更节省资源,只在需要的时候加载动态库的某个函数,省空间,提速度,而隐式就是方便啦,在运行之前全部动态库加载完毕
实例
写一个简单的例子来查看各个段信息
1 |
|
编译生成可执行文件main,
输入nm main
查看符号信息
1 | 0000000000601068 B __bss_start |
可以发现:
- gNoData未初始化,在bss段
- gData,globalStr,globalPStr均初始化,在data段
使用objdump -s main
查看各个段的详细信息如下,去掉其中一些我们不关注的段信息
1 | Contents of section .text: |
可以发现:
- 其中使用char *str方式指向字符串的,字符串均保存在常量区,也就是.rodata
- 宏定义中的字符串和printf中的格式化输出信息也在.rodata中
- 而使用char str[]=“xxx”方式的字符串,全局变量保存在.data段,而局部变量则是保存在了.text代码段,在程序运行时直接赋值