Вопрос по math, c, linker-errors, undefined-reference – У меня была та же проблема, которая исчезла после того, как я в последний раз перечислил свою библиотеку: gcc prog.c -lm

87

от вопрос уже есть ответ здесь:

неопределенная ссылка на sqr# (или другие математические функции) 4 ответа

У меня есть следующий код (урезанный до базовых основ для этого вопроса):

#include&l#;s#dio.h&g#;
#include&l#;ma#h.h&g#;

double f1(double x)
{
    double res = sin(x);
    re#urn 0;
}

/* The main func#ion */
in# main(void)
{
    re#urn 0;
}

При компиляции сgcc #es#.c Я получаю следующую ошибку и не могу понять, почему:

/#mp/ccOF5bis.o: In func#ion `f1':
#es#2.c:(.#ex#+0x13): undefined reference #o `sin'
collec#2: ld re#urned 1 exi# s#a#us

Тем не менее, я написал различные тестовые программы, которые вызываютsin изнутриmain функции, и те работают отлично. Должно быть, я делаю что-то явно не так - но что это?

@peoro, меня это не удивит. Это очень распространенная «забытая» библиотека. Edwin Buck

Ваш Ответ

4   ответа
37

$ gcc -Wall foo.c -o foo -lm 
60

В любом случае у меня проблема с добавлением -lm

gcc -Wall -lm mtest.c -o mtest.o
mtest.c: In function 'f1':
mtest.c:6:12: warning: unused variable 'res' [-Wunused-variable]
/tmp/cc925Nmf.o: In function `f1':
mtest.c:(.text+0x19): undefined reference to `sin'
collect2: ld returned 1 exit status

Недавно я обнаружил, что это не работает, если вы сначала укажете -lm. Порядок имеет значение:

gcc mtest.c -o mtest.o -lm

Просто ссылка без проблем

Таким образом, вы должны указать библиотеки после.

Это проблема, которая давала сбои в gcc с тех пор :) Я думал, что пять лет и два основных релиза вылечили бы его, но он все еще здесь! Забавно :) Lorenzo Dematté
У меня тоже была такая же проблема подать в суд на последнюю версию gcc 4.9 Santi
Рад сообщить, что этого не происходит с gcc 5.4 или gcc 6.2.1. Pockets
Всегда связывайте библиотеки после объектных файлов. Это всегда работает. Связывание библиотек перед объектными файлами иногда работает, а иногда нет. (Есть случайные исключения - но они встречаются очень редко, и вы будете знать, когда это уместно и что делать, потому что руководства по используемой вами библиотеке скажут вам, или потому что вы написали руководство.) Jonathan Leffler
9

которая исчезла после того, как я в последний раз перечислил свою библиотеку: gcc prog.c -lm

106

math.h, но когда вы попытались связать его, вы забыли о возможности включить библиотеку математики. В результате вы можете скомпилировать ваши объектные файлы .o, но не создавать свой исполняемый файл.

Как уже упоминал Павел, добавьте-lmmsgstr "связать с библиотекой математики на шаге, где вы пытаетесь сгенерировать свой исполняемый файл.

вкомментарий, linuxD спрашивает:

Зачемsin() в<math.h>нам нужно-lm вариант явно; но не дляprintf() в<stdio.h>?

Потому что обе эти функции реализованы как часть «Единой спецификации UNIX». Эта история этого стандарта интересна и известна под многими именами (IEEE Std 1003.1, Руководство по переносимости X / Open, POSIX, Spec 1170).

Это стандарт,специально выделяет подпрограммы «Стандартная библиотека С» из подпрограмм «Стандартная математическая библиотека С» (стр. 277), Соответствующий отрывок скопирован ниже:

Стандартная библиотека C

Стандартная библиотека C автоматически ищетсяcc разрешить внешние ссылки. Эта библиотека поддерживает все интерфейсы базовой системы, как определено в томе 1, за исключением математических процедур.

Стандартная математическая библиотека C

Эта библиотека поддерживает математические процедуры базовой системы, как определено в томе 1.cc вариант-lm используется для поиска в этой библиотеке.

Обоснование этого разделения зависит от ряда факторов:

UNIX войны привело к растущему расхождению с оригинальным предложением AT & T UNIX.Количество платформ UNIX добавило трудностей в разработке программного обеспечения для операционной системы.Была предпринята попытка определить наименьший общий знаменатель для разработчиков программного обеспечения,называется 1988 POSIX.Разработчики программного обеспечения запрограммированы в соответствии со стандартом POSIX для предоставления своего программного обеспечения в «POSIX-совместимых системах», чтобы охватить больше платформ.Клиенты UNIX требовали «UNIX-системы», совместимые с POSIX, для запуска программного обеспечения.

Давление, которое подпитывало решение поставить-lm в другой библиотеке, вероятно, включены, но не ограничиваются:

Кажется, это хороший способ уменьшить размер libc, так как многие приложения не используют функции, встроенные в математическую библиотеку.Это обеспечивает гибкость в реализации математической библиотеки, где некоторые математические библиотеки полагаются на большие встроенные справочные таблицы, в то время как другие могут полагаться на меньшие справочные таблицы (вычислительные решения).Для действительно ограниченных по размеру приложений это позволяет переопределять математическую библиотеку нестандартным способом (например, простоsin() и положить его в пользовательскую библиотеку.

В любом случае, теперь это часть стандарта, которая не будет автоматически включена как часть языка C, и поэтому вы должны добавить-lm.

Обратите внимание, что системная библиотека на Mac (под управлением Mac OS X или macOS) содержит математические функции. Существует библиотека для удовлетворения ссылок на-lm в сборках, но вам не нужно использовать-lm связать математические функции. Основная проблема, приводившая к отделению математической библиотеки от остальных, заключалась в том, что процессоры не всегда имели встроенную функцию с плавающей запятой; были сопроцессоры с плавающей запятой (80387 и т. д.) и т. д., поэтому было много способов обеспечить функциональность (использование программных библиотек с плавающей запятой или аппаратного обеспечения с различной степенью поддержки). Jonathan Leffler
Также обратите внимание, что современная спецификация POSIX дляc99 «расширенное описание - стандартные библиотеки» определяет библиотеки несколько по-другому, отмечая, что содержание-lm (как один из множества других) могут быть связаны без необходимости явного упоминания в командной строке связывания. Цитата в ответе от SVID 4-е издание (от июля 1995 года). Это исторически актуально, но больше не является определяющим. Jonathan Leffler
@KeithThompson Добавил много к ответу, чтобы убить комментарий. Наслаждаться. Edwin Buck
почему для sin (math.h) нам нужна явно опция -lm, но не для printf () fn, определенной в stdio.h, я сомневаюсь в возможностях компоновщика GNU. Как и в VCC он работает и на Mac тоже, как упоминалось flarn2006. linuxD

Похожие вопросы