Я выполняю некоторые тесты с 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
и связал его с a.out
при компиляции main.c
.
Перечисление символов 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
будет разумно определять ненужные символы для исключения.
Выше приведены мои гипотезы, основанные на этом эксперименте - но насколько это правильно? Если кто-то разбирается в тонкостях работы ссылок, я был бы благодарен за некоторую справочную информацию, объясняющую, почему и почему происходит то, что происходит.