Niezdefiniowane odniesienie do „pow” i „floor”

124

Próbuję zrobić prosty kalkulator Fibonacciego w C, ale podczas kompilacji gccmówi mi, że brakuje mi funkcji pow i floor. Co jest nie tak?

Kod:

#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));
}

Wynik:

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
Gabriele Cirulli
źródło
Ponieważ precyzja zmiennoprzecinkowa nie jest nieskończona, da to błędne odpowiedzi dla niezbyt dużych wartościn
vonbrand
Wygląda na to, że istnieje jeszcze łatwiejsze rozwiązanie, po prostu użyj zamiast tego g ++: g ++ fib.c -o fibo
OrenIshShalom

Odpowiedzi:

242

Musisz skompilować się z flagą linku -lm, na przykład:

gcc fib.c -lm -o fibo

To powie gcc, aby połączyć twój kod z biblioteką matematyczną. Po prostu pamiętaj, aby umieścić flagę po obiektach, które chcesz połączyć.

Fred
źródło
7
Czy mógłbyś wyjaśnić, jak opracować literę umieszczaną po -l?
Gabriele Cirulli
48
Zajrzyj do / lib lub / usr / lib. Wszystkie biblioteki są nazwane lib<name>.alub lib<name>.so- to „<nazwa>”, którą wstawiasz po -l. W tym przypadku nazwa biblioteki matematycznej libm.so, więc ją nazywamy -lm.
AMS
3
Dzięki! Szukam w Google przez ostatnie 30 minut i jest to pierwsza wzmianka o powiązaniu bibliotek po obiektach
Dave Baghdanov,
Możesz również użyć LD_PRELOAD, aby powiedzieć konsolidatorowi środowiska wykonawczego ld, aby włączył libm.so do mapy pamięci i tabeli symboli procesu, aby te symbole zostały załadowane i wszystko działa zgodnie z oczekiwaniami
debuti
Dziękuję za odpowiedź. Ale czy ktoś może mi powiedzieć, dlaczego w przypadku kodów z kilkoma wierszami jest to w porządku, nawet jeśli nie dołączę -lm podczas kompilacji?
MItrajyoti Kusari
24

Dodaj -lm do opcji linków, ponieważ pow () i floor () są częścią biblioteki matematycznej:

gcc fib.c -o fibo -lm
Yann Droneaud
źródło
9

Z korzyścią dla każdego, kto to przeczyta później, musisz połączyć się z tym, jak powiedział Fred:

gcc fib.c -lm -o fibo

Dobrym sposobem, aby dowiedzieć się, do której biblioteki chcesz linkować, jest sprawdzenie strony podręcznika, jeśli taka istnieje. Na przykład man powiman floor obie powie ci:

Połącz z -lm .

Wyjaśnienie łączenia biblioteki matematycznej w programowaniu w C - Łączenie w C

spike.barnett
źródło
8

W odniesieniu do odpowiedzi udzielonej przez Fuzzy:

Właściwie musiałem zrobić coś nieco innego.

Projekt -> Właściwości -> C / C ++ Kompilacja -> Ustawienia -> GCC C Linker -> Biblioteki

Kliknij małą zieloną ikonę dodawania, wpisz mi naciśnij OK. Wszystko w tym oknie ma automatycznie zastosowane -l, ponieważ jest to biblioteka.

Greg K.
źródło
6

Znalezienie punktu, w którym dodać -lm w Eclipse-IDE jest naprawdę okropne, więc zajęło mi to trochę czasu.

Jeśli ktoś inny również używa Edlipse, oto sposób dodania polecenia:

Projekt -> Właściwości -> Kompilacja C / C ++ -> Ustawienia -> GCC C Linker -> Różne -> Flagi konsolidatora: w tym polu dodaj polecenie -lm

Zamazany
źródło
0

Wszystkie powyższe odpowiedzi są niekompletne, problem tkwi w konsolidatorze, lda nie w kompilatorze collect2: ld returned 1 exit status. Podczas kompilowania fib.cobiektu do obiektu:

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

Gdzie nmwyświetla symbole z pliku obiektowego. Możesz zobaczyć, że zostało to skompilowane bez błędu, ale pow, floori printffunkcje mają niezdefiniowane odniesienia, teraz, jeśli spróbuję połączyć to z plikiem wykonywalnym:

$ 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

Otrzymuję podobne wyniki. Aby to rozwiązać, muszę powiedzieć linkerowi, gdzie szukać odniesień pow, iw floortym celu użyję -lflagi linkera, z mktórą pochodzi z libm.sobiblioteki.

$ 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__

Możesz teraz zobaczyć, funkcje pow, z floorktórymi są połączoneGLIBC_2.2.5 .

Kolejność parametrów też jest ważna, chyba że twój system jest skonfigurowany do korzystania z bibliotek współdzielonych domyślnie, mój system nie jest, więc kiedy wydaję:

$ 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

Uwaga -lmflaga przed plikiem obiektu. Podsumowując -lm, dla pewności dodaj flagę po wszystkich innych flagach i parametrach.

bladekp
źródło