c - 为什么公共(public)部分变量只出现在目标文件中而不是可执行文件中?

标签 c gcc objdump compiler-flags

我试图更多地了解可执行文件的“公共(public)”部分,我注意到在编译代码上执行 objdump 时,我可以看到仅在对象上的公共(public)代码中放置的变量文件 (*.o) 不在可执行文件中。

这是为什么?

//test.c

int i[1000];
int main(){return 0;}

构建命令:

> gcc -g0 -fcommon -c test.c
> gcc -g0 -fcommon test.c

objdump 在符号表的公共(public)部分显示i:

> objdump -x test.o
  ...
  SYMBOL TABLE:
  ...
  00000fa0    O   *COM*   00000020  i

除非我在可执行文件上运行它:

> objdump -x a.out
  ...
  SYMBOL TABLE:
  ...
  0804a040 g  O   .bss    00000fa0  i

如果我用 -fno-common 标志重建目标文件,它会显示在 .bss 段中,就像在可执行文件中一样。最终的可执行文件没有这个“COMMON”部分吗?

最佳答案

公共(public)部分是链接器知道的内容。它基本上将所有 common 内容放入 [典型] 可执行文件具有的三个或四个实际部分之一(代码或文本、数据、bss - 有时也有 rodata)。

因此,在这种情况下,您的变量最终以 .bss 结尾,因为它们没有被初始化。

来自 -fcommon/-fno-common 的 gcc 手册>

In C code, controls the placement of uninitialized global variables. Unix C compilers have traditionally permitted multiple definitions of such variables in different compilation units by placing the variables in a common block. This is the behavior specified by -fcommon, and is the default for GCC on most targets. On the other hand, this behavior is not required by ISO C, and on some targets may carry a speed or code size penalty on variable references. The -fno-common option specifies that the compiler should place uninitialized global variables in the data section of the object file, rather than generating them as common blocks. This has the effect that if the same variable is declared (without extern) in two different compilations, you get a multiple-definition error when you link them. In this case, you must compile with -fcommon instead. Compiling with -fno-common is useful on targets for which it provides better performance, or if you wish to verify that the program will work on other systems that always treat uninitialized variable declarations this way.

因此,-fno-common-fcommon 只会在有多个名为 i 的全局变量时产生差异 [并且它们应该具有相同的大小,否则你的程序将变得无效,这比未定义的行为差一个等级!]

关于c - 为什么公共(public)部分变量只出现在目标文件中而不是可执行文件中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14840126/

相关文章:

linux - 计算函数在内存中的偏移量

c - 带有调试信息的二进制文件的 objdump 产生损坏的输出

c - 是否可以用位而不是字节来执行 memcpy?

c - 移植到较新的 OpenCV 'C' 接口(interface);未找到 cv.h 文件

c - 用C程序写header?

c - 内联汇编时如何防止GCC警告函数没有返回?

c++ - “优化”属性指令被忽略

c - 分析 ELF 部分和符号大小的工具

c++ - 如何使用 Doxygen 注释生成的代码

c - 在 C 中为结构内的指针分配和分配内存?