为什么局部静态变量是 BSS 段的一部分?

deb*_*deb 2 c c++ gcc

静态内存布局的 BSS 部分[应该]用于“未初始化的全局变量”或“全局变量设置为 0”。

\n

我正在运行一些测试,突然注意到局部静态变量也在增加 BSS 段的大小。

\n

例子 :-

\n

在任何静态变量之前

\n
int main (int argc, char argv[])\n{\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n
data/repos/e-c \n\xe2\x9d\xaf size a.out \n   text   data     bss     dec     hex  filename\n   1418    544       8    1970     7b2  a.out\n
Run Code Online (Sandbox Code Playgroud)\n

静态变量之后

\n
int main (int argc, char *argv[])\n{\n    static int a, b, c;\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n
data/repos/e-c \n\xe2\x9d\xaf !s\nsize a.out \n   text   data     bss     dec     hex  filename\n   1418    544      16    1978     7ba  a.out\n
Run Code Online (Sandbox Code Playgroud)\n

这些变量肯定不是全局变量,那为什么BSS段会增加呢?或者“未初始化的全局变量的段”的想法不完全正确?

\n

目前我使用的是 Linux,并使用 GCC 编译器(版本 9.3.0)。

\n

Joh*_*ger 6

静态内存布局的 BSS 部分[应该]用于“未初始化的全局变量”或“全局变量设置为 0”。

目前还不清楚你从哪里得到这种印象,但它充其量只是一种误导。大多数人在 C 上下文中使用术语“全局变量”意味着具有外部链接的对象标识符,这对于具有静态存储持续时间的对象来说是必然的。有一些附带条件,这样的标识符可以在程序中的任何地方使用来引用同一对象,因此是“全局的”。一些附带条件的存在和性质使用“全球”一词来表示这些有点令人担忧,但我将把它留给不同的答案。

BSS 的关键点不是链接,而是存储持续时间。静态存储持续时间意味着,至少在原则上,对象在程序开始时或之前就存在*并且(至少)生存到程序终止。与在不带 的块作用域中声明的变量对比static:这些变量具有自动存储持续时间,这意味着它们在声明时就存在,并且仅存活到最内层包含块的执行终止为止。

具有静态存储持续时间的对象需要在程序映像中表示,无论它们的链接如何,因为它们与程序本身具有相同的生命周期。C 指定,如果此类对象未显式初始化,则它们的初始值就像初始化为 0(对于数字类型)或NULL(指针类型)或按成员方式初始化为这些(对于复合类型)。BSS 是一种节省空间和时间的快捷方式,用于表示此类对象以及显式初始化为 0 的对象的存储。

满足初始化条件的所谓“全局”变量可以并且通常归因于 BSS,但也可以

  • 具有内部链接的文件范围变量(该范围内声明的影响static;这些变量自动具有静态存储持续时间,但只能从一个源文件访问,并且
  • 具有静态存储持续时间的块作用域变量,通过static在该作用域使用关键字来指定,即使它们没有链接

*在 C++ 中,其中一些对象稍后会进行动态初始化,但此类对象的内存仍然为程序的整个运行保留,并且它们在程序启动时会进行零初始化。它们具有保留的记忆和明确定义的价值,构成了本答案的存在。

  • 不是这样,@MooingDuck,至少在 C 中不是这样。我建议您参考 C 语言规范的第 6.2.4/3 段:“一个对象,其标识符在没有存储类说明符 _Thread_local 的情况下声明,并且具有外部或内部链接或者使用存储类说明符 static,具有静态存储持续时间。它的生命周期是程序的整个执行过程,并且其存储的值仅在程序启动之前初始化一次。” (3认同)
  • @MooingDuck 对于 C++ 来说基本上是正确的,这清楚地说明了为什么许多双重标记的问题不应该被回答或非常小心地回答。尽管情况比这稍微复杂一些,但从某种意义上说,JohnBollinger 和 MooingDuck 都是正确的,尽管他们似乎在说不同的事情。静态存储持续时间变量通常初始化两次:一次静态初始化,根据 6.9.3.2/1“作为程序启动的结果”,一次动态初始化。根据 8.8/4“控制第一次通过其声明”...... (2认同)