Riferimento indefinito a "pow" e "floor"


124

Sto cercando di creare un semplice calcolatore di Fibonacci in C ma durante la compilazione gccmi dice che mi mancano le funzioni pow e floor. Cosa c'è che non va?

Codice:

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

Produzione:

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

Poiché la precisione in virgola mobile non è infinita, ciò darà risposte sbagliate per valori non così grandi din
vonbrand


Sembra che esista una soluzione ancora più semplice, usa semplicemente g ++ invece: g ++ fib.c -o fibo
OrenIshShalom

Risposte:


242

Devi compilare con il flag di collegamento -lm, in questo modo:

gcc fib.c -lm -o fibo

Questo dirà a gcc di collegare il tuo codice alla libreria matematica. Assicurati solo di mettere il flag dopo gli oggetti che vuoi collegare.


7
Potresti spiegare come elaborare la lettera da mettere dopo -l?
Gabriele Cirulli

48
Cerca in / lib o / usr / lib. Le librerie hanno tutte un nome lib<name>.ao lib<name>.so- è "<name>" che hai messo dopo -l. In questo caso, la libreria matematica è denominata libm.so, quindi la chiamiamo -lm.
AMS

3
Grazie! Ho cercato su Google negli ultimi 30 minuti e questo è il primo riferimento che diceva di collegare le biblioteche dopo gli oggetti
Dave Baghdanov

Puoi anche usare LD_PRELOAD per dire a ld runtime linker di includere libm.so nella mappa di memoria e nella tabella dei simboli del processo, in modo che questi simboli vengano caricati e tutto funzioni come previsto
debuti

Grazie per la risposta. Ma qualcuno può dirmi perché in caso di codici con poche righe va bene anche se non includo -lm durante la compilazione?
MItrajyoti Kusari

24

Aggiungi -lm alle tue opzioni di collegamento, poiché pow () e floor () fanno parte della libreria matematica:

gcc fib.c -o fibo -lm

9

A beneficio di chiunque legga questo in seguito, è necessario collegarsi ad esso come ha detto Fred:

gcc fib.c -lm -o fibo

Un buon modo per scoprire quale libreria è necessario collegare è controllare la pagina man se ne esiste una. Ad esempio, man powe man floorti diranno entrambi:

Collegamento con -lm.

Una spiegazione per il collegamento di librerie matematiche nella programmazione C - Collegamento in C


8

Per quanto riguarda la risposta fornita da Fuzzy:

In realtà ho dovuto fare qualcosa di leggermente diverso.

Progetto -> Proprietà -> Build C / C ++ -> Impostazioni -> GCC C Linker -> Librerie

Fare clic sulla piccola icona verde di aggiunta, digitare me premere ok. Tutto in questa finestra viene applicato automaticamente -l poiché è una libreria.


6

Trovare il punto in cui aggiungere -lm in Eclipse-IDE è davvero orribile, quindi mi ci è voluto del tempo.

Se qualcun altro usa anche Edlipse, ecco come aggiungere il comando:

Project -> Properties -> C / C ++ Build -> Settings -> GCC C Linker -> Miscelleaneous -> Linker flags: in questo campo aggiungi il comando -lm


0

Tutte le risposte sopra sono incomplete, il problema qui sta nel linker ldpiuttosto che nel compilatore collect2: ld returned 1 exit status. Quando stai compilando il tuo fib.coggetto:

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

Dove nmelenca i simboli dal file oggetto. Puoi vedere che questo è stato compilato senza errori, ma pow, floore le printffunzioni hanno riferimenti non definiti, ora se cercherò di collegarlo all'eseguibile:

$ 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

Sto ottenendo un output simile che ottieni. Per risolverlo, devo dire al linker dove cercare i riferimenti powe floor, a questo scopo, userò il -lflag del linker con mcui proviene dalla libm.solibreria.

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

Ora puoi vedere, le funzioni pow, floorsono collegate a GLIBC_2.2.5.

Anche l'ordine dei parametri è importante, a meno che il tuo sistema non sia configurato per utilizzare le librerie condivise per impostazione predefinita, il mio sistema non lo è, quindi quando emetto:

$ 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

Nota -lmflag prima del file oggetto. Quindi, in conclusione, aggiungi -lmflag dopo tutti gli altri flag e parametri, per sicurezza.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.