gcc non includerà correttamente math.h

gcc non includerà correttamente math.h


Ecco un esempio minimo che delinea il mio problema


test.c:


#include <stdio.h>
#include <math.h>
main ()
{
fmod ( 3, 2 );
}

Ed ecco il comando che sto emettendo per compilare test.c


gcc -lm test.c -o test

Ed ecco l'output che ottengo quando eseguo il comando precedente


/tmp/ccQmRk99.o: In function `main':
test.c:(.text+0x3e): undefined reference to `fmod'
collect2: ld returned 1 exit status

Ottengo lo stesso output se invece utilizzo cc . Sto usando la seguente versione di gcc


gcc-4.6.real (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1

Qualche idea sul perché il mio programma non viene compilato?


Risposte:


Il problema proviene dal linker, ld , piuttosto che gcc (da cui il messaggio di stato di uscita). In generale ld richiede che gli oggetti e le librerie siano specificati nell'ordine user supplier , dove user è un oggetto che utilizza una funzione di libreria e supplier è l'oggetto che lo fornisce.


Quando il tuo test.c viene compilato in un oggetto il compilatore afferma che fmod è un riferimento indefinito


$ gcc -c test.c
$ nm test.o
U fmod
0000000000000000 T main

(nm elenca tutte le funzioni a cui fa riferimento un file oggetto)


Il linker cambia i riferimenti non definiti in quelli definiti, cercando i riferimenti per vedere se sono forniti in altri file.


$ gcc -lm test.o
$ nm a.out
0000000000600e30 d _DYNAMIC
0000000000600fe8 d _GLOBAL_OFFSET_TABLE_
00000000004006a8 R _IO_stdin_used
w _Jv_RegisterClasses
0000000000600e10 d __CTOR_END__
...
0000000000601018 D __dso_handle
w __gmon_start__
...
U [email protected]@GLIBC_2.2.5
0000000000601020 A _edata
0000000000601030 A _end
0000000000400698 T _fini
0000000000400448 T _init
0000000000400490 T _start
00000000004004bc t call_gmon_start
0000000000601020 b completed.7382
0000000000601010 W data_start
0000000000601028 b dtor_idx.7384
U [email protected]@GLIBC_2.2.5
0000000000400550 t frame_dummy
0000000000400574 T main

La maggior parte di questi si riferisce a funzioni libc eseguite prima e dopo main per configurare l'ambiente. Puoi vedere che fmod ora punta a glibc, dove verrà risolto dal sistema di libreria condivisa.


Il mio sistema è configurato per utilizzare le librerie condivise per impostazione predefinita. Se invece forzo il collegamento statico, ottengo la dipendenza dell'ordine che vedi


$ gcc -static -lm test.o
test.o: In function `main':
test.c:(.text+0x40): undefined reference to `fmod'
collect2: ld returned 1 exit status

Inserendo -lm più avanti nel comando linker, dopo test.o , gli consente di collegarsi correttamente.
Il controllo dei simboli fmod ora dovrebbe essere risolto in un indirizzo reale, e in effetti lo è


$ gcc -static test.o -lm
$ nm a.out | grep fmod
0000000000400480 T __fmod
0000000000402b80 T __ieee754_fmod
0000000000400480 W fmod