我正在使用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
在编译
main.c
时,我已经将bar.o
连接到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()
不在了。从这个实验中,我可以得出以下“规则”:
- 从对象文件链接的符号始终存在于可执行文件中。(也许这就解释了为什么
foo()
始终存在:是否有一个临时/匿名的main.o
被创建了?如果是这样,它会包含foo()
) - 如果可执行文件与一个库链接,
gcc
会智能地找出不必要的符号来排除。
gcc --version
"的输出。 - StoneThrow