【问题标题】:Why differentiate BSS and COMMON section?为什么要区分 BSS 和 COMMON 部分?
【发布时间】:2020-12-18 00:18:35
【问题描述】:

我相信我的问题是不同的to this one。在这里我问为什么我们需要区分这两者,链接只回答哪个去哪个。

我们知道:

  • Common 部分用于未初始化的全局变量和

  • Bss 部分用于未初始化的静态变量和初始化为 0 的全局变量。

但是为什么要区分 BSS 和 COMMON 部分呢?特别是对于初始化为0的全局变量,我们不能将它们放在用于初始化全局变量的.data部分吗?把变量初始化为0不也是初始化吗?

以下是我教科书中的解释:

在某些情况下,链接器允许多个模块定义具有相同名称的全局符号。当编译器在翻译某个模块时遇到一个弱全局符号,比如 x,它不知道其他模块是否也定义了 x,如果是,它无法预测链接器可能选择 x 的多个实例中的哪一个。因此编译器通过将 x 分配给 COMMON 将决定推迟到链接器。另一方面,如果 x 被初始化为零,那么它是一个强符号,因此编译器可以放心地将它分配给 bss。

我真的很困惑,它说“它不知道其他模块是否也定义了x”,但是你怎么能定义一个变量两次呢?有示例代码来说明吗?

【问题讨论】:

    标签: c gcc


    【解决方案1】:

    .bss 部分用于分配零初始化数据以进行优化,以允许

    • 静态链接器减少可执行文件大小(但不存储零)
    • 运行时链接器(加载器)以加快加载过程:公共数据可以通过映射填充零的专用物理页面或在启动时memseting 内存来有效地初始化。

    Common 部分用于(在某些平台上,例如Windows,但不是 ELF)来实现所谓的“通用符号”,即可以在不同目标文件中重复的符号(“翻译单元”)。当此类符号属于公共部分时,静态链接器将合并所有单独的定义(具有一些特定于平台的规则,例如仅在相同时合并,首选最大定义等)。

    在某些目标上,公共部分仅用于未初始化的数据(这使得它们与.bss 有点相似),而在其他目标上也用于vague symbols。一般来说,为什么不同平台在公共部分的使用上做出不同的选择没有合乎逻辑的原因,这纯粹是历史原因。

    您可以在 [Raymond Chen 的文章] 中找到一些常见符号背后的历史 (https://devblogs.microsoft.com/oldnewthing/20161024-00/?p=94575)。

    【讨论】:

    • 谢谢你的回答,但这不是我的教科书建议的,你能再看看我的帖子吗,我补充一下
    • ELF 也有共同点。
    • @R..GitHubSTOPHELPINGICE ELF 有通用符号,但我不知道通用部分。
    猜你喜欢
    • 1970-01-01
    • 2013-05-09
    • 2014-04-05
    • 2019-01-28
    • 1970-01-01
    • 2011-11-14
    • 2013-05-26
    • 1970-01-01
    • 2012-03-21
    相关资源
    最近更新 更多