Referência indefinida a `pow 'e` floor'

124

Estou tentando fazer uma calculadora de fibonacci simples em C, mas quando a compilação gccme diz que estou perdendo as funções pow e floor. O que há de errado?

Código:

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

Resultado:

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
fonte
Como a precisão de ponto flutuante não é infinito, isso vai dar respostas erradas para não tão grandes valores den
vonbrand
Parece que uma solução ainda mais fácil existe, basta usar g ++ em vez disso: g ++ fib.c -o fibo
OrenIshShalom

Respostas:

242

Você precisa compilar com o sinalizador de link -lm, desta forma:

gcc fib.c -lm -o fibo

Isso instruirá o gcc a vincular seu código à biblioteca matemática. Apenas certifique-se de colocar a bandeira após os objetos que você deseja vincular.

Fred
fonte
7
Poderia explicar como elaborar a carta para colocar depois de -l?
Gabriele Cirulli
48
Procure em / lib ou / usr / lib. As bibliotecas são todas nomeadas lib<name>.aou lib<name>.so- é o "<name>" que você coloca após o -l. Nesse caso, a biblioteca de matemática é nomeada libm.so, como chamamos -lm.
29711
3
Obrigado! Estive pesquisando para os últimos 30 minutos e esta é a primeira referência que disse para ligar as bibliotecas após os objetos
Dave Baghdanov
Você também pode usar LD_PRELOAD para dizer ld runtime vinculador para incluir libm.so no mapa de memória e símbolo da tabela do processo a, assim que estes símbolos são carregados e tudo funciona como esperado
debuti
Obrigado pela resposta. Mas alguém pode me dizer por que, no caso de códigos com algumas linhas, está tudo bem, mesmo que eu não inclua -lm durante a compilação?
MItrajyoti Kusari 28/02/19
24

Adicione -lm às suas opções de link, pois pow () e floor () fazem parte da biblioteca de matemática:

gcc fib.c -o fibo -lm
Yann Droneaud
fonte
9

Para o benefício de quem ler isso mais tarde, é necessário vincular-se a ele, como Fred disse:

gcc fib.c -lm -o fibo

Uma boa maneira de descobrir qual biblioteca você precisa vincular é verificando a página de manual, se houver alguma. Por exemplo, man powe man floorambos lhe dirão:

Vincular com -lm.

Uma explicação para vincular a biblioteca matemática na programação C - Vinculando em C

spike.barnett
fonte
8

Em relação à resposta fornecida por Fuzzy:

Na verdade, eu tive que fazer algo um pouco diferente.

Projeto -> Propriedades -> Compilação C / C ++ -> Configurações -> GCC C Linker -> Bibliotecas

Clique no pequeno ícone verde de adição, digite me pressione ok. Tudo nesta janela foi automaticamente aplicado a -l, pois é uma biblioteca.

Greg K
fonte
6

Encontrar o ponto em que adicionar o -lm no Eclipse-IDE é realmente horrível, por isso levei algum tempo.

Se alguém também usar o Edlipse, veja como adicionar o comando:

Projeto -> Propriedades -> Compilação C / C ++ -> Configurações -> Vinculador do GCC C -> Diversos -> Sinalizadores do vinculador: neste campo, adicione o comando -lm

Difusa
fonte
0

Todas as respostas acima estão incompletas, o problema aqui está no vinculador, lde não no compilador collect2: ld returned 1 exit status. Quando você está compilando seu fib.cobjeto:

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

Onde nmlista símbolos do arquivo de objeto. Você pode ver que esta foi compilado sem um erro, mas pow, floore printffunções têm referências indefinidas, agora se eu vou tentar ligar este ao executável:

$ 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

Estou obtendo resultados semelhantes. Para resolver isso, preciso informar ao vinculador onde procurar referências powe floor, para esse fim, utilizarei o -lsinalizador de vinculador com o mqual vem da libm.sobiblioteca.

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

Agora você pode ver, as funções pow, floorestão ligados a GLIBC_2.2.5.

A ordem dos parâmetros também é importante, a menos que seu sistema esteja configurado para usar bibliotecas compartilhadas por padrão, meu sistema não é, portanto, quando emito:

$ 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

Observe o -lmsinalizador antes do arquivo do objeto. Portanto, em conclusão, adicione -lmsinalizador após todos os outros sinalizadores e parâmetros, para ter certeza.

bladekp
fonte