Я пытаюсь связать модуль C++ с использованием GCC, по сути, как это:Код ссылки GCC изменен?
gcc -c hello.c
g++ -c world.cpp
gcc -ohello -lstdc++ hello.o world.o
Обратите внимание, что я использую -lstdc++
связать модуль C++ в, так что я могу использовать gcc
вместо g++
. Проблема заключается в том, что я получаю сообщение об ошибке:
undefined reference to `operator new(unsigned long)'
(Предполагая, что world.cpp
содержит, по меньшей мере, один вызов new
.)
Эта ошибка исправлена, если я ставлю -lstdc++
в конце линкера линии , например:
gcc -ohello hello.o world.o -lstdc++
Я знаю, что этот вопрос задавался много раз здесь, но у меня есть специальное требование. Я напрямую не звоню в GCC. Я использую систему сборки для другого языка программирования (Mercury), который вызывает от меня GCC, и я не могу легко изменить способ его вызова GCC (хотя я могу указать дополнительные библиотеки, используя переменную среды LDFLAGS). Так что у меня есть два дополнительных требования:
- Я не могу использовать
g++
связать (толькоgcc
) - вот почему я делаю-lstdc++
трюк выше, чем просто связь сg++
). - Я не думаю, что могу контролировать порядок команд компоновщика - Mercury поместит файлы .o в командной строке после любых библиотек.
Я понимаю основную причину, почему порядок важен, но то, что сбивает с толку меня это почему этот перерыв сейчас? Я просто обновился до Ubuntu 11.10/GCC 4.6.1. Я успешно скомпилировал эту программу в течение многих лет, используя именно эту технику (сначала ставил -lstdc++
). Только теперь эта ошибка возникла. Несвязанная программа моих ссылок на OpenGL с использованием -lgl
, и это тоже сломалось, когда я обновился, и мне пришлось переместить -lgl
в конец командной строки. Вероятно, я узнаю, что десятки моих программ больше не компилируются. Почему это изменилось? Что-то не так с моей новой системой, или так, как сейчас? Обратите внимание, что это обычные общие библиотеки, а не статически связанные.
Есть ли что-нибудь, что я могу сделать, чтобы GCC вернулась к старому пути, где порядок библиотек не имеет значения? Есть ли другой способ, которым я могу убедить GCC правильно связать libstdc++
, не перемещая его после файлов .o
в командной строке?
Итак, в основном этот «регресс» - это только для моей карьеры развития, я полагался на то, что он «случайно работал», и теперь он перестает работать? Похоже, это довольно серьезное изменение - я помещал библиотеки перед объектными файлами в течение большей части десятилетия, потому что я понятия не имел, что это проблема :(Спасибо за совет.Похоже, проблема заключалась не в том, что объекты Mercury помещаются после библиотек, но в моей команде LDFLAGS есть более сложные зависимости. Я добиваюсь прогресса, поэтому я дам вам галочку. Благодарю. – mgiuca
Неподтвержденная гипотеза: возможно, произошли изменения в 'ld', которые влияют на вас. Целью может быть избежать загрузки неиспользуемых разделяемых библиотек. Если вы используете статические библиотеки, вы получаете только то, что вам нужно. Раньше было, что если вы указали общую библиотеку в линии ссылок, она будет загружена во время выполнения, даже если библиотека не предоставила никаких символов. Только загрузка библиотеки, если она удовлетворяет хотя бы одному символу, может сократить время запуска программы. Но это также означает, что если единственным выдающимся символом при сканировании библиотеки является 'main()', то библиотека не будет загружена. –
Просмотреть комментарии о '--as-needed' для версии 2.20' ld' в [НОВОСТИ] (http://sourceware.org/cgi-bin/cvsweb.cgi/~checkout//src/ld/NEWS? rev = 1.121 & content-type = text/plain & cvsroot = src & only_with_tag = binutils-binutils-2_22). См. Также [manual] (http://sourceware.org/binutils/docs-2.22/ld/Options.html#Options) и '-copy-dt-required-entries' и' -no-copy- dt-required-entries'. Я полагаю, что предыдущая гипотеза - хотя бы несколько доказана. –