Неопределенная ссылка на `pow 'и` floor'

124

Я пытаюсь сделать простой калькулятор Фибоначчи на C, но при компиляции gccсообщает мне, что мне не хватает функций pow и floor. В чем дело?

Код:

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

int fibo(int n);

int main() {
        printf("Fib(4) = %d", fibo(4));
        return 0;
}

int fibo(int n) {
        double phi = 1.61803399;

        return (int)(floor((float)(pow(phi, n) / sqrt(5)) + .5f));
}

Вывод:

gab@testvm:~/work/c/fibo$ gcc fib.c -o fibo
/tmp/ccNSjm4q.o: In function `fibo':
fib.c:(.text+0x4a): undefined reference to `pow'
fib.c:(.text+0x68): undefined reference to `floor'
collect2: ld returned 1 exit status
Габриэле Чирулли
источник
Поскольку точность с плавающей запятой не бесконечна, это даст неправильные ответы для не очень больших значенийn
vonbrand
Похоже, что существует еще более простое решение, просто используйте вместо него g ++: g ++ fib.c -o fibo
OrenIshShalom

Ответы:

242

Вам нужно скомпилировать с флагом ссылки -lm, например:

gcc fib.c -lm -o fibo

Это скажет gcc связать ваш код с математической библиотекой. Только не забудьте поставить флажок после объектов, которые вы хотите связать.

Фред
источник
7
Не могли бы вы объяснить, как написать букву после -l?
Габриэле Чирулли,
48
Посмотрите в / lib или / usr / lib. Все библиотеки имеют имена lib<name>.aили lib<name>.so- это "<имя>", которое вы ставите после -l. В этом случае математическая библиотека названа libm.soтак, как мы ее называем -lm.
AMS
3
Спасибо! Я гуглил последние 30 минут, и это первая ссылка, в которой говорится, что библиотеки нужно связывать после объектов
Дэйв Багданов
Вы также можете использовать LD_PRELOAD, чтобы указать компоновщику времени выполнения ld включить libm.so в карту памяти и таблицу символов процесса, чтобы эти символы загружались, и все
работало,
Спасибо за ответ. Но может ли кто-нибудь сказать мне, почему в случае кодов с несколькими строками это нормально, даже если я не включаю -lm при компиляции?
MItrajyoti Kusari
24

Добавьте -lm к параметрам ссылки, поскольку pow () и floor () являются частью математической библиотеки:

gcc fib.c -o fibo -lm
Янн Дроно
источник
9

Для тех, кто прочтет это позже, вам нужно дать ссылку на это, как сказал Фред:

gcc fib.c -lm -o fibo

Хороший способ узнать, какую библиотеку нужно связать, - это проверить страницу руководства, если таковая существует. Например,man pow иman floor оба скажут вам:

Связать с -lm .

Объяснение связывания математической библиотеки в программировании на C - Связывание в C

spike.barnett
источник
8

Что касается ответа, предоставленного Fuzzy:

На самом деле мне пришлось сделать что-то немного другое.

Проект -> Свойства -> Сборка C / C ++ -> Настройки -> Компоновщик GCC C -> Библиотеки

Щелкните маленький зеленый значок добавления, введите m и нажмите ОК. Ко всему в этом окне автоматически применяется -l, поскольку это библиотека.

Грег К
источник
6

Найти точку, в которой добавить -lm в Eclipse-IDE, действительно ужасно, поэтому мне потребовалось время.

Если кто-то еще использует Edlipse, вот как добавить команду:

Проект -> Свойства -> Сборка C / C ++ -> Настройки -> GCC C Linker -> Разное -> Флаги компоновщика: в это поле добавьте команду -lm

нечеткий
источник
0

Все ответы выше неполны, проблема здесь в компоновщике, ldа не в компиляторе collect2: ld returned 1 exit status. Когда вы компилируете свой fib.cобъект to:

$ gcc -c fib.c
$ nm fib.o
0000000000000028 T fibo
                 U floor
                 U _GLOBAL_OFFSET_TABLE_
0000000000000000 T main
                 U pow
                 U printf

Где nmперечисляет символы из объектного файла. Вы можете видеть, что это было скомпилировано без ошибок, но pow, floorи printfфункции имеют неопределенные ссылки, теперь, если я попытаюсь связать это с исполняемым файлом:

$ gcc fib.o
fib.o: In function `fibo':
fib.c:(.text+0x57): undefined reference to `pow'
fib.c:(.text+0x84): undefined reference to `floor'
collect2: error: ld returned 1 exit status

Я получаю тот же результат, что и вы. Чтобы решить эту проблему, мне нужно указать компоновщику, где искать ссылки pow, и floorдля этой цели я буду использовать -lфлаг компоновщика, mкоторый поступает из libm.soбиблиотеки.

$ gcc fib.o -lm
$ nm a.out
0000000000201010 B __bss_start
0000000000201010 b completed.7697
                 w __cxa_finalize@@GLIBC_2.2.5
0000000000201000 D __data_start
0000000000201000 W data_start
0000000000000620 t deregister_tm_clones
00000000000006b0 t __do_global_dtors_aux
0000000000200da0 t 
__do_global_dtors_aux_fini_array_entry
0000000000201008 D __dso_handle
0000000000200da8 d _DYNAMIC
0000000000201010 D _edata
0000000000201018 B _end
0000000000000722 T fibo
0000000000000804 T _fini
                 U floor@@GLIBC_2.2.5
00000000000006f0 t frame_dummy
0000000000200d98 t __frame_dummy_init_array_entry
00000000000009a4 r __FRAME_END__
0000000000200fa8 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
000000000000083c r __GNU_EH_FRAME_HDR
0000000000000588 T _init
0000000000200da0 t __init_array_end
0000000000200d98 t __init_array_start
0000000000000810 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
0000000000000800 T __libc_csu_fini
0000000000000790 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
00000000000006fa T main
                 U pow@@GLIBC_2.2.5
                 U printf@@GLIBC_2.2.5
0000000000000660 t register_tm_clones
00000000000005f0 T _start
0000000000201010 D __TMC_END__

Теперь вы можете видеть, функции pow, floorкоторые связаны с GLIBC_2.2.5.

Порядок параметров также важен, если ваша система не настроена на использование общих библиотек по умолчанию, моя система нет, поэтому, когда я выдаю:

$ gcc -lm fib.o
fib.o: In function `fibo':
fib.c:(.text+0x57): undefined reference to `pow'
fib.c:(.text+0x84): undefined reference to `floor'
collect2: error: ld returned 1 exit status

Отметьте -lmфлаг перед объектным файлом. Итак, в заключение, добавьте -lmфлаг после всех других флагов и параметров, чтобы быть уверенным.

bladekp
источник