Я работаю над большим проектом. И теперь столкнулись с ошибкой ссылки.
Эту ошибку можно избежать с помощью обходного пути, но я не могу понять, почему он работает.
Вот структура файла, связанная с моей проблемой:
project |-package_a |--a.cpp |--... |-package_b |--b.cpp |--c.cpp |--... |-package_others
Все *.o в package_a будут упакованы в a.a, а *.o в package_b будут упакованы в b.a
"g++ -o exec -Bstatic b.a a.a ..."
используется для создания двоичного файла.
В package_b/b.cpp я добавил функцию foo().
И в package_a/a.cpp я использовал эту функцию.
Но здесь я получаю сообщение об ошибке ссылки, говорящее о неопределенной ссылке foo () в a.o
Я могу проверить (с помощью objdump), что foo() уже находится в b.o.
Изменив команду ссылки на "g++ -o exec -Bstatic a.a b.a ..."
, можно успешно построить двоичный файл. Теперь я понимаю, что компоновщик заботится о порядке в списке компоновки. Но, пожалуйста, поймите, что это большой проект. У меня нет разрешения изменять конфигурацию проекта, поэтому необходимо сохранить исходный порядок ссылок.
Затем я добавил фиктивную функцию bar() в package_b/c.cpp, которая ничего не делает, кроме вызова foo(), после чего исходный "g++ -o exec -Bstatic b.a a.a ..."
будет работать без ошибок связи.
Может ли кто-нибудь показать мне, почему просто добавление фиктивной функции в тот же пакет будет работать в этом случае?
Я использую g++ 4.4.4 и Linux 2.6.18-194.el5.
Любой комментарий будет оценен
Could be that another function of package_b/c.cpp was already referenced, and the linker took bar() with it (because they are in the same file) and this referenced foo(), which was subsequently included in the output, too. It succeeded, because foo was in b.a too.
‹br/›У меня все еще есть сомнения по этому поводу, вы имеете в виду, что на package_b/c.cpp уже ссылались до обработки компоновщика a.a? но как не может быть ошибки ссылки, когда она ссылается на эти символические символы в package_b/c.cpp? 07.11.2011b.a
. Может быть файл, содержащийmain
, могут быть какие-то неопределенные символы из предыдущих аргументов. В любом случае, компилятор видит c.cpp (в b.a) и foo.cpp (в b.a), по какой-то причине нуждается в c.cpp, который, в свою очередь, требует foo.cpp. a.a не имеет к этому никакого отношения, за исключением того, что позже он выигрывает от того, чтоfoo
уже включен в вывод. 08.11.2011*.a
не работает, а с*.a *.a
нет. Спасибо за объяснение. Я предполагаю, что это побочный эффект использования архивов, в котором некоторые объектные файлы могут быть нужны немедленно, а другие нет. 23.01.2014