it-swarm-ru.tech

Неопределенная ссылка на `sin`

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

#include<stdio.h>
#include<math.h>

double f1(double x)
{
    double res = sin(x);
    return 0;
}

/* The main function */
int main(void)
{
    return 0;
}

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

/tmp/ccOF5bis.o: In function `f1':
test2.c:(.text+0x13): undefined reference to `sin'
collect2: ld returned 1 exit status

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

89
robintw

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

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

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

Почему для sin() в <math.h>, нужна ли нам опция -lm явно; но не для printf() в <stdio.h>?

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

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

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

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

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

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

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

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

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

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

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

109
Edwin Buck

В любом случае у меня проблема с добавлением -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

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

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

61
Anyeos

Вам нужно связаться с математической библиотекой libm:

$ gcc -Wall foo.c -o foo -lm 
38
Paul R

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

10
blackappy