确定目标文件上的BSS大小

时间:2014-04-28 07:24:26

标签: c gcc linker

Wikipedia提到" bss部分通常包括在文件范围内声明的所有未初始化的变量。"给出以下文件:

int uninit;

int main() {
    uninit = 1;
    return 0;
}

当我将其编译为可执行文件时,我看到正确填充了bss段:

$ gcc prog1.c -o prog1
$ size prog1
text       data     bss     dec     hex filename
1115        552       8    1675     68b prog1

但是,如果我将其编译为目标文件,我就不会看到bss段(我希望它是4):

$ gcc -c prog1.c
$ size prog1.o 
text       data     bss     dec     hex filename
  72          0       0      72      48 prog1.o

我有什么明显的遗失吗?

我正在使用gcc版本4.8.1。

1 个答案:

答案 0 :(得分:7)

如果我们使用readelf -s查看符号表,我们会看到:

$ readelf -s prog1.o

Symbol table '.symtab' contains 10 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS bss.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4 
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    6 
     6: 0000000000000000     0 SECTION LOCAL  DEFAULT    7 
     7: 0000000000000000     0 SECTION LOCAL  DEFAULT    5 
     8: 0000000000000004     4 OBJECT  GLOBAL DEFAULT  COM uninit      <<<<
     9: 0000000000000000    16 FUNC    GLOBAL DEFAULT    1 main

我们发现您的uninit符号(&#34;变量&#34;)在此阶段是一个常见的&#34;符号。它尚未被分配&#34;到BSS。

有关&#34;常见&#34;的更多信息,请参阅此问题。符号:What does "COM" means in the Ndx column of the .symtab section?

将最终的可执行文件链接在一起后,它将按预期放入BSS。


您可以通过将-fno-common标志传递给GCC来绕过此行为:

$ gcc -fno-common -c bss.c
$ size bss.o
   text    data     bss     dec     hex filename
     72       0       4      76      4c bss.o

相反,您可以将uninit标记为static。通过这种方式,编译器将知道没有其他.o文件可以引用它,因此它不会是&#34; common&#34;符号。相反,它会立即按照您的预期放入BSS:

$ cat bss.c
static int uninit;

int main() {
    uninit = 1;
    return 0;
}
$ gcc -c bss.c 
$ size bss.o
   text    data     bss     dec     hex filename
     72       0       4      76      4c bss.o