【问题标题】:Why don't I get static variables in the BSS?为什么我没有在 BSS 中获得静态变量?
【发布时间】:2016-01-15 01:25:16
【问题描述】:

据我所知,未显式初始化的静态变量(对于 GCC,即使设置了 -fzero-initialized-in-bss,即使是那些显式初始化为零的变量,默认情况下也是如此)通常存储在BSS 段。然而,似乎当我尝试检查该行为时,这些变量存储在通用数据部分(具有初始化的全局变量)。如果我编译(使用-O0 进行很好的衡量)并运行:

#include <stdio.h>
#include <stdlib.h>

extern char etext, edata, end;

int i = 42;

int main(int argc, char* argv[])
{
        static int j;
        printf ("end of program (etext) = %10p\n",&etext);
        printf ("end of initialized data (edata) = %10p\n",&end);
        printf ("end of uninitialized data (end) = %10p\n",&end);
        printf ("=====\n");
        printf ("Value of i (initialized global) : %d\n",i);
        printf ("Address of i : %10p\n",&i);
        printf ("Value of j (static with no explicit initialization) : %d\n",j);
        printf ("Address of i : %10p\n",&j);
        return 0;
}

我得到了输出:

end of program (etext) =   0x40067d
end of initialized data (edata) =   0x600af0
end of uninitialized data (end) =   0x600af0
=====
Value of i (initialized global) : 42
Address of i :   0x600ae0
Value of j (static with no explicit initialization) : 0
Address of i :   0x600ae8

所以ij 存储在&amp;etext&amp;edata 之间的连续内存地址,这是常规数据部分。此外,&amp;edata == &amp;end 似乎意味着 BSS 是空的。

现在我意识到编译器将哪个变量放在哪里是一个实现选择,它产生的结果是正确的。但我只是想知道为什么我会出现这种行为,以及是否有办法告诉 gcc 明确地将这些变量放在 BSS 中(我在手册中没有看到任何明显的解决方案)。

【问题讨论】:

  • 您的代码为 edata 和 end 打印 &end,这是复制粘贴问题还是造成这种混乱的原因?

标签: c gcc memory


【解决方案1】:

可执行映像中的 BSS 只是一个数字,表示在加载时为未初始化的变量保留多少字节。这样,对于许多这些未初始化的变量,图像不会变得太大。当数字非常小时,例如在您的示例中,几乎没有任何节省,只有开销,编译器可能已决定将它们全部放在 DATA 段中。

【讨论】:

  • 好的,我明白它为什么有意义了。您是否知道是否有明确告诉 GCC 不要这样做并无论如何都要创建 BSS 的方法?仅用于教学目的。
【解决方案2】:

您的代码中有错误。您为 edata 和 end 打印了 end 的地址,因此您当然假设 edata == end,但事实并非如此。

当我修复你的代码并运行它时,我得到:

程序结束 (etext) = 0x8048578
初始化数据结束 (edata) = 0x804988c
未初始化数据结束(结束)= 0x8049894

i 的值(初始化全局):42
我的地址:0x8049888
j 的值(没有显式初始化的静态):0
j的地址:0x8049890

很明显,j 位于 edata 和 end 之间的区域,而不是与 i 相同的位置。

(gcc 5.2.1 20150911(Debian 5.2.1-17),32 位)

【讨论】:

  • 你是绝对正确的。谢谢你。我很惭愧以前没有看过它-_-
猜你喜欢
  • 2010-10-10
  • 2021-05-29
  • 1970-01-01
  • 2012-08-29
  • 2018-05-23
  • 2014-01-15
  • 2012-02-01
  • 1970-01-01
相关资源
最近更新 更多