gpt4 book ai didi

c - C 链接器何时以及为何会排除未使用的符号?

转载 作者:太空狗 更新时间:2023-10-29 14:56:55 25 4
gpt4 key购买 nike

我正在使用 gcc 执行一些测试,以了解它智能排除未使用符号的规则。

// main.c

#include <stdio.h>

void foo()
{
}

int main( int argc, char* argv[] )
{
return 0;
}

.

// bar.c

int bar()
{
return 42;
}

.

> gcc --version
gcc (GCC) 8.2.1 20181215 (Red Hat 8.2.1-6)
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
>
> gcc -c bar.c
> gcc -g main.c bar.o
> nm a.out | grep "foo\|bar"
000000000040111f T bar
0000000000401106 T foo

上面我编译了bar.o,在编译main.c的时候用a.out链接了
列出 a.out 的符号表明两个未使用的函数 - foo()bar() - 都包含在可执行文件中。

> ar -r libbar.a bar.o
ar: creating libbar.a
> gcc -g main.c -L ./ -lbar
> nm a.out | grep "foo\|bar"
0000000000401106 T foo

上面,我已经将 bar.o 归档到 libbar.a,并重新创建了 a.out,这次链接到 libbar.a 而不是 bar.o。这一次,未使用的函数 foo() 仍然存在,但 bar() 不存在。

从这个实验中,我可能会推测出以下“规则”:

  1. 从目标文件链接的符号总是出现在可执行文件中。 (也许这解释了为什么 foo() 总是存在:是否创建了一个临时/匿名的 main.o?如果是这样,它将包括 foo() )
  2. 如果可执行文件与 链接,gcc 将智能地找出不需要的符号以排除。

以上是我基于这个实验的假设 - 但它的正确性如何?如果有人了解链接工作的复杂性,我将不胜感激一些背景信息来解释正在发生的事情的原因和原因。

最佳答案

静态库链接并不真正具有每个符号的粒度,这在大多数情况下是正确的。它具有每个成员对象文件的粒度。

示例:

如果静态库包含文件:

a.o 
foo
bar
b.o
baz

并且需要解析对 foo 的 undefined reference ,a.o 将被引入,同时 bar 符号也会被引入。

当你用-ffunction-sections -fdata-sections 编译然后用-Wl链接时,你可以得到每个符号粒度的效果,-- gc-sections(gc 代表垃圾收集),但请记住,编译器/链接器选项是特定于 gcc/clang 的,并且它们具有一些较小的性能/代码大小成本。

-ffunction-sections 将每个函数放在它自己的部分(有点像它自己的目标文件)并且 -fdata-sections 为外部可见的全局做同样的事情变量。 -Wl,--gc-sections 然后会导致垃圾收集器在对象文件照常链接后运行,并且垃圾收集器会删除所有无法访问的部分(=> 符号)。

(-ffunction-sections 也很有用,如果您希望 size -A the_objectfile.o 为您提供函数大小,并且如果您还希望这些函数大小不会根据功能的位置略有波动(由于对齐要求)。)

关于c - C 链接器何时以及为何会排除未使用的符号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55130965/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com