Visualizzazione post con etichetta librerie dinamiche. Mostra tutti i post
Visualizzazione post con etichetta librerie dinamiche. Mostra tutti i post

martedì 15 dicembre 2009

Undefined reference to...

"Undefined reference to:" è un messaggio di errore che può essere restituito dal linker ld, utilizzato di default dal gcc.
La stringa sopracitata compare seguita dal nome di una funzione per la quale il linker non è in grado di identificare un riferimento valido: in altre parole il linker non sa dove prendere il codice corrispondente a quella funzione.
Il problema è dovuto ad una di queste due cause:

  • non è stato incluso l'header file contenente la definizione della funzione utilizzata;

  • l'header è presente ma la funzione appartiene ad una libreria dinamica (o condivisa).


Nel primo caso, ovviamente, è sufficiente aggiungere l'include mancante.
Nel secondo, invece, è necessario utilizzare un'opportuna opzione di compilazione che permetterà al linker ld di trovare il codice corrispondente alla funzione utilizzata. Esiste un'opzione specifica per ogni libreria condivisa installata sul proprio sistema: tutte hanno la forma -l<id>, dove <id> è una stringa ti testo che identifica la specifica libreria.
Ecco alcuni esempi particolarmente comuni:

  • -lm (libreria matematica, math.h)

  • -lncurses (libreria grafica ncurses, ncurses.h)

  • -lpthread (libreria per thread POSIX, pthread.h)


Di seguito un esempio di utilizzo:
 gcc main.c -o main -lm 

C: Math.h e undefined reference to...

Imbattersi in un errore come il seguente è particolarmente pericoloso se non si sa di cosa si tratta, in questo caso la soluzione, banale, sarebbe ardua da identificare.

    /tmp/cctraBp0.o: In function `main': 
run.c:(.text+0x34): undefined reference to `sqrt'
collect2: ld returned 1 exit status
In questo esempio ho compilato un programma molto semplice:

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

int main()
{
double x = 2.0;

printf("Hello (%lf).\n", sqrt(x));

return 0;
}
Qui viene utilizzata una funzione della libreria matematica, sqrt, e viene opportunamente incluso l'header math.h, ma la libreria matematica del C appartiene ad una speciale categoria di librerie, quella delle librerie dinamiche o condivise (shared libraries).
Quando si usa una di queste librerie non è sufficiente includerla nel codice, si rende necessario utilizzare delle opzioni di compilazione. Per compilare correttamente questo programma senza ottenere errori dal linker (ld), dobbiamo aggiungere l'opzione -lm, in questo modo:
 gcc run.c -o run -lm 
In questo modo si otterrà un eseguibile perfettamente funzionante senza errori di linking.

ATTENZIONE: quando si usano versioni recenti di gcc (sicuramente dalla versione 4.3.1 in poi) l'utilizzo dell'opzione -lm è necessario soltanto se si utilizzano le funzioni matematiche insieme a variabili. Se invocassimo sqrt con una costante come argomento, il gcc sostituisce l'invocazione della funzione con il suo risultato ed il codice corrispondente alla invocazione della funzione matematica non viene generato. Per questo non c'è bisogno di aggiungere l'opzione del linker che permette il caricamento dinamico della libreria a run-time. Il seguente codice, ad esempio:

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

int main()
{
printf("Hello (%lf).\n", sqrt(2.0));

return 0;
}
può essere compilato correttamente con il seguente comando:
 gcc run.c -o run 

senza che il linker restituisca alcun errore.