【问题标题】:Local and static variables in C (cont'd)C 中的局部变量和静态变量(续)
【发布时间】:2012-11-27 11:14:28
【问题描述】:

在我的last question 的基础上,我试图弄清楚.local.comm 指令是如何工作的,特别是它们如何影响C 中的链接和持续时间。

所以我进行了以下实验:

static int value;

生成以下汇编代码(使用 gcc):

.local  value
.comm   value,4,4

当初始化为零时产生相同的汇编代码(使用 gcc):

.local  value
.comm   value,4,4

这听起来合乎逻辑,因为在这两种情况下,我都希望变量将存储在 bss 段中。此外,在使用ld --verbose 进行调查后,看起来所有.comm 变量确实都放在了bss 段中:

  .bss            :
  {
   *(.dynbss)
   *(.bss .bss.* .gnu.linkonce.b.*)
   *(COMMON)
   // ...
  }

当我将变量初始化为非零值时,编译器会按照我的预期在数据段中定义变量,但会产生以下输出:

        .data
        .align 4
        .type   value, @object
        .size   value, 4
value:
        .long   1

除了之前我现在理解的不同部分(分别为 bss 和数据)之外,我的变量在第一个示例中被定义为 .local.comm 而在第二个示例中没有。谁能解释每个案例产生的两个输出之间的差异?

【问题讨论】:

    标签: c gcc assembly static


    【解决方案1】:

    .local 指令将符号标记为本地的、外部不可见的符号,如果它不存在则创建它。对于 0 初始化的局部符号,这是必需的,因为 .comm 声明但不定义符号。对于 1 初始化的变体,符号本身 (value:) 声明了该符号。

    使用.local.comm 本质上是一种技巧(或者至少是一种速记);另一种方法是将符号显式放入.bss

            .bss
            .align 4
            .type   value, @object
            .size   value, 4
    value:
            .zero   4
    

    【讨论】:

    • .comm 没有.local 也可以工作(链接器将定义符号),但它将是全局可见和共享的。顺便说一句,GAS 也有.lcomm
    • @Jester .comm 没有 .local 在 C 中没有多大意义(不过它在 Fortran 中可能很有用)。 .lcomm 未在此处使用,因为它不允许指定对齐方式(在此平台上)。
    【解决方案2】:

    出于安全原因,Linux 内核在分配后会将进程的虚拟内存归零。因此,编译器已经知道内存将被零填充并进行优化:如果某个变量初始化为 0,则无需在可执行文件中为其保留空间(.data 部分实际上在 ELF 中占用了一些空间可执行文件,而.bss 部分仅存储其长度,假设其初始内容为零)。

    【讨论】:

    • 感谢您的反馈,但我的问题实际上是关于在第一种情况下添加 .local 和 .comm 指令,而不是在第二种情况下。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-04
    • 1970-01-01
    • 1970-01-01
    • 2016-04-24
    • 2012-06-18
    • 2018-04-18
    • 1970-01-01
    相关资源
    最近更新 更多