为什么需要.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 ?** */
}
提问于 2018-04-18

2 个回答

用户回答回答于 2018-04-18

原因是减少程序大小。假设你的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可能是一个非常高效的内联汇编器,这意味着启动拷贝可以更快地执行。

 
 
用户回答回答于 2018-04-18

.bss细分是一种优化。整个.bss段由单个数字描述,可能是4个字节或8个字节,它在运行过程中给出了它的大小,而该.data段与初始化变量的大小总和一样大。因此,.bss使可执行文件更小更快加载。否则,变量可以在.data显式初始化为零的段中; 该计划将难以区分。(具体来说,.bss如果它位于.data段中,则对象的地址可能与地址不同。)

在第一个程序中,a将在该.data段中并且b将在.bss该可执行文件的段中。一旦程序加载完毕,这种区别变得无关紧要。在运行时,b占用20 * sizeof(int)字节。

在第二个程序中,var分配空间和分配以main()修改该空间。恰恰var是在.bss段中描述了空间而不是.data段,但是这并不影响程序在运行时的行为方式。

posted @ 2022-02-20 20:51  edward_liu2000  阅读(146)  评论(0编辑  收藏  举报