113 votes

Référence indéfinie à `sin`.

J'ai le code suivant (réduit à l'essentiel pour cette question) :

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

double f1(double x)
{
    double res = sin(x);
    return 0;
}

/* The main function */
int main(void)
{
    return 0;
}

En le compilant avec gcc test.c J'obtiens l'erreur suivante, et je n'arrive pas à comprendre pourquoi :

/tmp/ccOF5bis.o: In function `f1':
test2.c:(.text+0x13): undefined reference to `sin'
collect2: ld returned 1 exit status

Cependant, j'ai écrit plusieurs programmes de test qui appellent sin de l'intérieur de la main et ceux-ci fonctionnent parfaitement. Je dois faire quelque chose de manifestement faux ici - mais qu'est-ce que c'est ?

1 votes

0 votes

@peoro, ça ne me surprendrait pas. C'est une bibliothèque "oubliée" très courante.

139voto

Edwin Buck Points 33097

Vous avez compilé votre code avec des références au bon fichier d'en-tête math.h, mais lorsque vous avez tenté de le lier, vous avez oublié l'option permettant d'inclure la bibliothèque mathématique. En conséquence, vous pouvez compiler vos fichiers objets .o, mais pas construire votre exécutable.

Comme Paul l'a déjà mentionné, ajoutez " -lm "pour établir un lien avec la bibliothèque mathématique dans l'étape où vous tentez de générer votre exécutable.

Dans le commentaire , linuxD demande :

Pourquoi pour sin() sur <math.h> avons-nous besoin -lm l'option explicitement ; mais pas pour printf() sur <stdio.h> ?

Car ces deux fonctions sont implémentées dans le cadre de la "spécification UNIX unique". L'histoire de cette norme est intéressante, et est connue sous de nombreux noms (IEEE Std 1003.1, X/Open Portability Guide, POSIX, Spec 1170).

Cette norme, sépare spécifiquement les routines de la "bibliothèque C standard" des routines de la "bibliothèque mathématique C standard" (page 277) . Le passage pertinent est copié ci-dessous :

Bibliothèque C standard

La bibliothèque C standard est automatiquement recherchée par cc pour résoudre les références externes. Cette bibliothèque prend en charge toutes les interfaces du système de base, telles qu'elles sont définies dans le Volume 1, à l'exception des routines mathématiques.

Bibliothèque mathématique standard en C

Cette bibliothèque prend en charge les routines mathématiques du système de base, telles que définies dans le volume 1. Le site cc option -lm est utilisé pour effectuer des recherches dans cette bibliothèque.

Le raisonnement derrière cette séparation a été influencé par un certain nombre de facteurs :

  1. En Les guerres d'UNIX a conduit à une divergence croissante par rapport à l'offre originale d'AT&T UNIX.
  2. Le nombre de plates-formes UNIX a rendu plus difficile le développement de logiciels pour le système d'exploitation.
  3. Une tentative de définir le plus petit dénominateur commun des développeurs de logiciels a été lancée, appelé 1988 POSIX .
  4. Les développeurs de logiciels programmés contre la norme POSIX doivent fournir leurs logiciels sur des "systèmes conformes à la norme POSIX" afin d'atteindre davantage de plates-formes.
  5. Les clients UNIX ont exigé des systèmes UNIX "conformes à POSIX" pour exécuter le logiciel.

Les pressions qui ont alimenté la décision de mettre -lm dans une autre bibliothèque probablement inclus, mais ne sont pas limités à :

  1. Cela semble être un bon moyen de limiter la taille de la libc, car de nombreuses applications n'utilisent pas les fonctions intégrées dans la bibliothèque mathématique.
  2. Il offre une certaine souplesse dans la mise en œuvre des bibliothèques mathématiques, certaines bibliothèques mathématiques reposant sur des tables de consultation intégrées plus importantes, tandis que d'autres peuvent s'appuyer sur des tables de consultation plus petites (solutions de calcul).
  3. Pour les applications dont la taille est vraiment limitée, il est possible de réimplémenter la bibliothèque mathématique de manière non standard (par exemple, en retirant seulement les éléments suivants sin() et le mettre dans une bibliothèque personnalisée.

Quoi qu'il en soit, il fait maintenant partie de la norme pour ne pas être automatiquement inclus dans le langage C, et c'est pourquoi vous devez ajouter -lm .

4 votes

Pourquoi pour sin (math.h), nous avons besoin de l'option -lm explicitement mais pas pour printf() fn défini dans stdio.h, je doute des capacités du linker de GNU. Comme dans VCC cela fonctionne et sur mac aussi comme flarn2006 l'a mentionné.

2 votes

@KeithThompson J'ai ajouté beaucoup de choses à la réponse pour tuer le commentaire. Profitez-en.

0 votes

Notez que la bibliothèque système d'un Mac (exécutant Mac OS X ou macOS) comprend les fonctions mathématiques. Il existe une bibliothèque pour satisfaire les références à -lm dans les constructions, mais vous n'avez pas besoin d'utiliser -lm pour obtenir les fonctions mathématiques liées. Le problème majeur qui a conduit à la séparation de la bibliothèque mathématique du reste était que les processeurs n'avaient pas toujours la virgule flottante intégrée ; il y avait des coprocesseurs à virgule flottante (80387, etc.) et ainsi de suite, donc il y avait de nombreuses façons de fournir la fonctionnalité (en utilisant des bibliothèques logicielles de virgule flottante, ou en utilisant le matériel, avec différentes quantités de support).

76voto

Anyeos Points 171

J'ai toujours le problème avec -lm ajouté :

gcc -Wall -lm mtest.c -o mtest.o
mtest.c: In function 'f1':
mtest.c:6:12: warning: unused variable 'res' [-Wunused-variable]
/tmp/cc925Nmf.o: In function `f1':
mtest.c:(.text+0x19): undefined reference to `sin'
collect2: ld returned 1 exit status

J'ai découvert récemment que c'est le cas no fonctionnent si vous spécifiez -lm premier. L'ordre est important. Vous devez préciser -lm dernier comme ceci :

gcc mtest.c -o mtest.o -lm

Cela fonctionne sans problème.

Vous devez donc spécifier les bibliothèques à la fin.

0 votes

C'est un problème qui dérange gcc depuis toujours :) Je pensais que cinq ans et deux versions majeures l'auraient réglé, mais il est toujours là ! Amusant :)

0 votes

J'ai également eu le même problème en utilisant la dernière version de gcc 4.9.

0 votes

Je suis heureux de constater que cela ne se produit pas avec gcc 5.4 ou gcc 6.2.1.

42voto

Paul R Points 104036

Vous devez établir un lien avec la bibliothèque mathématique, libm :

$ gcc -Wall foo.c -o foo -lm

11voto

blackappy Points 326

J'ai eu le même problème, qui a disparu après avoir listé ma bibliothèque en dernier : gcc prog.c -lm

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X