gcc / ld: неопределенная ссылка на неиспользуемую функцию

#gcc #cygwin #ld

#gcc #cygwin #ld

Вопрос:

Я использую gcc 4.3.4 и ld 2.20.51 в Cygwin под Windows 7. Вот упрощенная версия моей проблемы:

  • foo.o содержит функцию, foo_bar() которая вызывает bar() в bar.o
  • bar.o содержит функцию bar()
  • main.c вызывает функции в foo.o , но foo_bar() не входит в цепочку вызовов

Если я попытаюсь скомпилировать main.c и связать его с foo.o, я получу undefined reference to _foo_bar ошибку от ld. Как вы можете видеть из моего Makefile, за исключением приведенного ниже, я пытался использовать флаги для помещения каждой функции в отдельный раздел и удаления компоновщиком неиспользуемых разделов.

 COMPILE_CYGWIN = gcc -iquote$(INCDIR)
COMPILE = $(COMPILE_CYGWIN) -g -MMD -MP -Wall -ffunction-sections -Wl,-gc-sections $(DEFINE)
main_OBJECTS = main.o foo.o
main.exe : $(main_OBJECTS)
    $(COMPILE) -o main.exe $(main_OBJECTS)
  

Функция foo_bar() — это короткая функция, которая обеспечивает соединение между двумя сетевыми уровнями в стеке протоколов. Некоторым программам это не нужно, поэтому они не будут ссылаться на другие объектные файлы, относящиеся к верхнему уровню стека. Это небольшая функция, и кажется неуместным помещать ее в собственный файл .o.

Я не понимаю, почему ld выдает ошибку — ничего не вызывается foo_bar() , поэтому нет необходимости включать bar() в конечный исполняемый файл. Коллега только что сказал мне, что ld это не «умный компоновщик», так что, возможно, то, что я пытаюсь сделать, невозможно?

Комментарии:

1. -ffunction-sections это было бы необходимо при компиляции foo . Есть ли какая-либо конкретная проблема со связыванием с bar также?

2. В этом случае для связывания bar.o требуется по крайней мере еще 15 объектных файлов для заполнения его зависимостей. Я думаю, что я достиг точки, когда мне нужно связать объектные файлы с библиотекой, и вместо этого мои программы ссылаются на это.

3. Если у вас нет других ограничений, это не так плохо, как кажется. Это небольшая предварительная проблема, но она не будет иметь каких-либо значительных затрат на время выполнения. Я не знаю, как работает динамический компоновщик в Windows, но предполагая, что он хотя бы наполовину приличный, этот посторонний код все равно никогда не будет загружен.

Ответ №1:

Если компоновщик не из Cyberdyne Systems, у него нет способа точно узнать, какие функции будут фактически вызваны. Он знает только, на какие из них есть ссылки. Даже компоновщик Skynet не может предсказать, какие решения будут приняты во время выполнения или что произойдет, если вы динамически загрузите модуль во время выполнения и он начнет вызывать различные глобальные функции1.

Итак, если вы ссылаетесь в модуле m и он ссылается на функцию f, вам нужно будет связать с любым модулем, имеющим f.


1. Эта проблема связана с проблемой остановки и, как оказалось, неразрешима.

Ответ №2:

Я столкнулся с аналогичной проблемой и нахожу эту страницу: http://lists.gnu.org/archive/html/bug-gnu-utils/2004-09/msg00098.html Главное: компоновщик GNU по-прежнему работает с детализацией файла .o. Gcc извлекает foo.o, а затем функция find bar() не была определена.

Вам лучше поместить foo_bar() в другой файл .o.