2016-09-28 4 views
6

Ich lese ein Buch mit dem Titel "Eine Einführung in GCC" und möchte eine Klarstellung. Das Buch zeigt an, dass der folgende Code einen Fehler verursachen aber wenn ich kompilieren, es baut und betreibt perfekt:gcc Linking mit statischen Bibliotheken

#include <math.h> 
#include <stdio.h> 
int main (void) { 
    double x = sqrt (2.0); 
    printf ("The square root of 2.0 is %f\n", x); 
    return 0; 
} 

ich aus dem Buch zitieren "Der Versuch, eine ausführbare Datei aus dieser Quelle allein zu erstellen bewirkt, dass der Compiler einen Fehler bei der Verbindung der Bühne geben: "

$ gcc -Wall calc.c -o calc 
/tmp/ccbR6Ojm.o: In function `main': 
/tmp/ccbR6Ojm.o(.text+0x19): undefined reference 
    to `sqrt' 

die Lösung, die das Buch gibt, ist, dass Sie sollen den Pfad zu der Mathematik-Bibliothek 'libm.a‘wie folgt:

$ gcc -Wall calc.c /usr/lib/libm.a -o calc 

wäre es sehr unbequem sein, um die Pfade zu integrierten Bibliotheken angeben zu müssen, die wir in unseren Programmen verwenden. Ich kann den Grund für das Hinzufügen des Pfades zu meinen eigenen benutzerdefinierten Bibliotheken verstehen, aber libm.a ist in gcc integriert. Und obwohl das Buch ziemlich alt ist (veröffentlicht im Jahr 2004), Was hat sich mit moderneren Versionen von gcc geändert, so dass wir den Pfad zu libm.a nicht brauchen?

* UPDATE *

Ich bemerkte, dass die von taskinoor gegebene Antwort Code aktualisiert zeigt, dass es erforderlich, dass ich die -Im Flag verwenden, wenn der Wert() sqrt nicht bestanden zum Zeitpunkt der Kompilierung bekannt ist.

Ich habe C/C++ mit VS gelernt, aber mein Ziel ist jetzt, gcc zu lernen und zu verwenden. Ich habe Visual Studio 2013 und der VS-Compiler/Linker scheint nicht so wählerisch. Zum Beispiel kann ich fast jedes einfache Programm kompilieren, ohne mysteriöse Compiler-Flags angeben zu müssen.

Ich lerne auf gcc Version 5.4, die mit KUbuntu kommt 16.04.1

+4

Versuchen Sie zuerst ein anderes Buch, da seit Jahrzehnten die Standardmethode zum Verknüpfen einer Math-Bibliothek die Verwendung von -lm anstelle eines vollständigen Pfads zur Bibliothek ist. Zweitens enthält https://gcc.gnu.org/releases.html die Release-Änderungen. –

+1

@JohnGriffin: Aus demselben Buch: * "Um zu vermeiden, dass lange Pfade in der Befehlszeile angegeben werden müssen, bietet der Compiler eine Abkürzungsoption '-l' für die Verknüpfung mit Bibliotheken. Beispiel: ' $ gcc -Wall calc.c -lm -o calc "entspricht dem ursprünglichen Befehl ..." * –

+0

Beachten Sie, dass heutzutage standardmäßig dynamische Bibliotheken und keine statischen Bibliotheken verwendet werden. Vielleicht wollten Sie fragen, ob Sie mit * Standard * -Bibliotheken verlinkt haben? – Barmar

Antwort

6

sqrt (2.0);

Moderne GCC ist gut in der Lage, um zu bestimmen, dass Sie Quadratwurzel einer konstanten versuchen zu finden und somit ist es kann das in der Kompilierzeit berechnen. Ihr Objektcode enthält keinen tatsächlichen Aufruf an sqrt.

Wenn Sie eine Variable verwenden, die über scanf bei Ausführung eingegeben wird, wird keine Verbindung ohne libm hergestellt.

int main() { 
    double x; 

    scanf("%lf", &x); 
    printf("%lf\n", sqrt(x)); 

    return 0; 
} 

Ohne libm gcc 4.8.4 auf Ubuntu 14.04 diese Ergebnisse:

/tmp/ccVO2fRY.o: In function `main': 
sqrt.c:(.text+0x2c): undefined reference to `sqrt' 
collect2: error: ld returned 1 exit status 

Aber wenn ich eine Konstante statt x wie Ihr Beispiel setzte dann verbindet sie ohne libm in Ordnung.

P.S: Ich weiß nicht die genaue Version seit wann GCC in der Lage ist, dies zu tun. Hoffentlich kann jemand anderes darauf hinweisen.

+0

Interessant ... Ich muss es überprüfen ... –

+0

Ich bekomme diesen Fehler auch unter Linux, aber keinen Fehler unter OS X. – Barmar

+0

@Barmar nein Linker-Fehler auf OS X mit Variablen, die zur Kompilierzeit nicht aufgelöst werden können? Tut mir leid, ich weiß nichts über OS X. Wahrscheinlich ist da noch etwas anderes los. – taskinoor

2

ich, dass Systeme auf einigen Betriebs bemerkt haben, sind gemeinsame Bibliotheken ohne explizite Verknüpfung zur Verfügung. Insbesondere habe ich oft ein funktionierendes C-Projekt gemacht, das ursprünglich auf meinem Mac entwickelt wurde, und das Projekt würde nicht unter Linux kompilieren, bis ich explizit gegen die Bibliotheken, die ich benutzt habe (wie libm), verlinkt habe.

Natürlich ist dies in der Regel für eine dynamische und nicht statische Linken ...

Verwandte Themen