Who*_*ami 107 c linux compiler-construction
我所知道的是全局和静态变量存储在.data段中,未初始化的数据存在于.bss段中.我不明白的是为什么我们有未初始化变量的专用段?如果未初始化的变量在运行时分配了值,那么该变量是否仅存在于.bss段中?
在以下程序中, a是在.data段中,并且b在.bss段中; 那是对的吗?如果我的理解是错误的,请纠正我.
#include <stdio.h>
#include <stdlib.h>
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
int b[20]; /* Uninitialized, so in the .bss and will not occupy space for 20 * sizeof (int) */
int main ()
{
;
}
Run Code Online (Sandbox Code Playgroud)
另外,请考虑以下程序,
#include <stdio.h>
#include <stdlib.h>
int var[10]; /* Uninitialized so in .bss */
int main ()
{
var[0] = 20 /* **Initialized, where this 'var' will be ?** */
}
Run Code Online (Sandbox Code Playgroud)
Lun*_*din 81
原因是减少了程序的大小.想象一下,您的C程序在嵌入式系统上运行,其中代码和所有常量都保存在真正的ROM(闪存)中.在这样的系统中,在调用main()之前,必须执行初始"copy-down"以设置所有静态存储持续时间对象.它通常会像这样伪:
for(i=0; i<all_explicitly_initialized_objects; i++)
{
.data[i] = init_value[i];
}
memset(.bss,
0,
all_implicitly_initialized_objects);
Run Code Online (Sandbox Code Playgroud)
其中.data和.bss存储在RAM中,但init_value存储在ROM中.如果它是一个段,则ROM必须填充大量零,从而显着增加ROM大小.
基于RAM的可执行文件的工作方式类似,但当然它们没有真正的ROM.
此外,memset可能是一些非常高效的内联汇编程序,这意味着可以更快地执行启动副本.
Jon*_*ler 74
该.bss细分是一种优化.整个.bss段由一个数字描述,可能是4个字节或8个字节,它在运行过程中给出了它的大小,而该.data部分与初始化变量的大小之和一样大.因此,.bss使可执行文件更小,更快地加载.否则,变量可以在.data段中显式初始化为零; 该计划将难以分辨出来.(详细地说,对象的地址.bss可能与地址中的地址不同.data.)
在第一个程序中,a将在.data段中并且b将位于.bss可执行文件的段中.加载程序后,区别变得无关紧要.在运行时,b占用20 * sizeof(int)字节.
在第二个程序中,var分配空间,分配main()修改该空间.碰巧var在.bss段中而不是.data段中描述了空间,但这不会影响程序在运行时的行为方式.
mih*_*hai 12
从汇编语言循序渐进: Jeff Duntemann 使用Linux进行编程,关于.data部分:
本.数据部分包含初始化的数据项的数据定义.初始化数据是在程序开始运行之前具有值的数据.这些值是可执行文件的一部分.当可执行文件加载到内存中以供执行时,它们将加载到内存中.
关于.data部分要记住的重要事项是,您定义的数据项越多,可执行文件就越大,运行时将它从磁盘加载到内存所需的时间就越长.
和.bss部分:
在程序开始运行之前,并非所有数据项都需要具有值.例如,当您从磁盘文件中读取数据时,您需要在从磁盘进入数据后获取数据.像这样的数据缓冲区在程序的.bss部分中定义.您为缓冲区留出了一些字节数并为缓冲区指定了名称,但是您没有说明缓冲区中存在哪些值.
.data部分中定义的数据项与.bss部分中定义的数据项之间存在重要差异:.data部分中的数据项会增加可执行文件的大小..bss部分中的数据项不是.可以在.bss中定义占用16,000字节(或更多,有时甚至更多)的缓冲区,并且几乎不添加任何内容(对于描述大约50个字节)到可执行文件大小.
好吧,首先,你的例子中的那些变量不是未初始化的; C指定未初始化的静态变量初始化为0.
因此.bss的原因是具有较小的可执行文件,节省空间并允许更快地加载程序,因为加载器可以只分配一堆零而不必从磁盘复制数据.
运行程序时,程序加载程序会将.data和.bss加载到内存中.写入驻留在.data或.bss中的对象只能进入内存,它们不会在任何时候刷新到磁盘上的二进制文件.
该系统V 4.1 ABI(1997)(AKA ELF规范),也包含了答案:
.bss此部分保存对程序内存映像有贡献的未初始化数据。根据定义,当程序开始运行时,系统用零初始化数据。该节不占用文件空间,如节类型SHT_NOBITS.
说节名.bss是保留的,有特殊效果,特别是不占用文件空间,因此比.data.
缺点当然是0当操作系统将它们放在内存中时,所有字节都必须设置为,这更具限制性,但很常见,并且适用于未初始化的变量。
该SHT_NOBITS部分类型的文档重复那肯定:
sh_size该成员以字节为单位给出节的大小。除非节类型是SHT_NOBITS,否则该节sh_size在文件中占用字节。type 的部分SHT_NOBITS可能具有非零大小,但它不占用文件中的空间。
C标准只字未提的部分,但我们可以很容易地验证对变量的存储在Linux中objdump和readelf,并得出结论,未初始化的全局其实都是存储在.bss。例如,请参阅此答案:C 中声明的未初始化变量会发生什么?
| 归档时间: |
|
| 查看次数: |
44370 次 |
| 最近记录: |