为什么需要.bss段?
我所知道的是,全局和静态变量存储在.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 ()
{
;
}
另外,请考虑下面的程序,
#include <stdio.h>
#include <stdlib.h>
int var[10]; /* Uninitialized so in .bss */
int main ()
{
var[0] = 20 /* **Initialized, where this 'var' will be ?** */
}
原因是减少程序大小。假设你的C程序运行在嵌入式系统上,代码和所有常量都保存在真正的ROM(闪存)中。在这样的系统中,在调用main()之前,必须执行初始“复制”以设置所有静态存储持续时间对象。它通常会像这样伪造:
for(i=0; i<all_explicitly_initialized_objects; i++)
{
.data[i] = init_value[i];
}
memset(.bss,
0,
all_implicitly_initialized_objects);
其中.data和.bss存储在RAM中,但init_value存储在ROM中。如果它是一个段,那么ROM必须填充很多零,从而显着增加ROM的大小。
基于RAM的可执行文件的工作方式类似,但它们当然没有真正的ROM。
另外,memset可能是一个非常高效的内联汇编器,这意味着启动拷贝可以更快地执行。
该.bss
细分是一种优化。整个.bss
段由单个数字描述,可能是4个字节或8个字节,它在运行过程中给出了它的大小,而该.data
段与初始化变量的大小总和一样大。因此,.bss
使可执行文件更小更快加载。否则,变量可以在.data
显式初始化为零的段中; 该计划将难以区分。(具体来说,.bss
如果它位于.data
段中,则对象的地址可能与地址不同。)
在第一个程序中,a
将在该.data
段中并且b
将在.bss
该可执行文件的段中。一旦程序加载完毕,这种区别变得无关紧要。在运行时,b
占用20 * sizeof(int)
字节。
在第二个程序中,var
分配空间和分配以main()
修改该空间。恰恰var
是在.bss
段中描述了空间而不是.data
段,但是这并不影响程序在运行时的行为方式。