GNUCompilerCollection/Linker-Fehler bei Fließkommazahlen: Unterschied zwischen den Versionen

Aus C3D2
Wechseln zu: Navigation, Suche
(hoffentlich verstaendliche erklaerung)
 
Zeile 1: Zeile 1:
Es handelt sich hier um einen Spezialfall beim GCC, andere Compiler verlangen dies nicht oder anders.
 
 
 
Das Bsp.:  
 
Das Bsp.:  
 
<code>
 
<code>
Zeile 33: Zeile 31:
 
:<code>gcc -lm anlagedauer.c</code>
 
:<code>gcc -lm anlagedauer.c</code>
 
damit die Quelle fehlerfrei baut.
 
damit die Quelle fehlerfrei baut.
 +
 +
'''Zur Erklaerung:''' der Linker der Gnu-Compiler-Collection der normalerweise auf x86 Systemen verwendet wird ist ld. Ld linkt standardmaessig C-Programme gegen 3 Bibliotheken:
 +
<code>
 +
$ ldd a.out
 +
        linux-vdso.so.1 (0x00007fff8edda000)
 +
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6f91338000)
 +
        /lib64/ld-linux-x86-64.so.2 (0x00007f6f916e2000)
 +
</code>
 +
 +
* linux-vdso.so.1 - Frueher auch linux-gate.so, ist ein virtual dynamic shared object. Es verbleibt im Addressraum eines jeden Prozesses und ermoeglicht es Nutzerprogrammen Systemfunktionen ueber die entsprechend vom Prozessor unterstuetzte Schnittstelle (frueher Software Interrupts, heute Fast System Call Interface) aufzurufen.
 +
* libc.so.6 - Ist deine libc, da ist die Implementation deiner Standardbibliothek verborgen.
 +
* ld-linux-x86-64.so.2 - Beinhaltet den Code der verantwortlich fuer das dynamische linken ist.
 +
 +
Moechte man das linken gegen diese 3 Bibliotheken unterbinden, so kann man dies tuen mit <code>-nostdlib</code> und <code>-nodefaultlibs</code> (siehe z.B. gcc manpage).
 +
Generell, muss man alle anderen Bibliotheken gegen die man linken moechte explizit angeben.
 +
 +
Warum die <code>libm</code> nicht in der <code>libc</code> enthalten ist hat historische Gruende die ich jetzt nicht ausfuehren moechte.
 +
 +
Desshalb muss man wenn die <code>math.h</code> genutzt wird mit <code>-lm</code> gelinkt werden.
 +
<code>
 +
$ ldd ./a.out
 +
        linux-vdso.so.1 (0x00007fff1a3fc000)
 +
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5b6af83000)
 +
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5b6abdb000)
 +
        /lib64/ld-linux-x86-64.so.2 (0x00007f5b6b286000)
 +
</code>
 +
 +
Wichtig ist jedoch das es sich hierbei um keinen Fehler oder ungewoehnliches Verhalten handelt. Die meisten C Compiler Verhalten sich so.
 +
Ich hoffe die kurze und sehr Oberflaechliche Erklaerung, tut nicht mehr fragen auf als sie beantwortet.
 +
 +
Ganz gute Referenzen sind:
 +
[http://www.ibm.com/developerworks/library/l-lpic1-v3-102-3/ Learn Linux, 101: Manage shared libraries]
 +
[http://www.network-theory.co.uk/docs/gccintro/ Introduction to GCC]
 +
[http://autotoolset.sourceforge.net/tutorial.html#SEC36 Learning the GNU development Tools]

Aktuelle Version vom 27. Oktober 2014, 10:13 Uhr

Das Bsp.:

 #include <stdio.h>
 #include <math.h>
 /*
   k = k0*(1+z)^n
   k/k0 = (1+z)^n
   log(k/k0) = log((1+z)^n)
    =n*log(1+z)
   n=log(k/k0)/og(1+z)
 */
 double anlagedauer(double k0, double k, double z){
   return log(k/k0)/log(1+z); 
 }       
        
 int main(){ 
   double k0=100, // startkapital
          k=110,  //endkapital
          z=0.01; //zins
   printf("Anlagedauer: %lf\n", anlagedauer(k0, k, z) );
   getchar();
   return 0;
 }

lässt sich nicht durch den einfachen Aufruf

gcc anlagedauer.c

compilieren, der Linker meldet "Fehler 1", auch die suche nach der math.h hilft hier nicht weiter, makros zur Steuerung der Header-Dateien sind hier also eine Sackgasse.

stattdessen muss die option -lm ergänzt werden

gcc -lm anlagedauer.c

damit die Quelle fehlerfrei baut.

Zur Erklaerung: der Linker der Gnu-Compiler-Collection der normalerweise auf x86 Systemen verwendet wird ist ld. Ld linkt standardmaessig C-Programme gegen 3 Bibliotheken: $ ldd a.out

       linux-vdso.so.1 (0x00007fff8edda000)
       libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6f91338000)
       /lib64/ld-linux-x86-64.so.2 (0x00007f6f916e2000)

  • linux-vdso.so.1 - Frueher auch linux-gate.so, ist ein virtual dynamic shared object. Es verbleibt im Addressraum eines jeden Prozesses und ermoeglicht es Nutzerprogrammen Systemfunktionen ueber die entsprechend vom Prozessor unterstuetzte Schnittstelle (frueher Software Interrupts, heute Fast System Call Interface) aufzurufen.
  • libc.so.6 - Ist deine libc, da ist die Implementation deiner Standardbibliothek verborgen.
  • ld-linux-x86-64.so.2 - Beinhaltet den Code der verantwortlich fuer das dynamische linken ist.

Moechte man das linken gegen diese 3 Bibliotheken unterbinden, so kann man dies tuen mit -nostdlib und -nodefaultlibs (siehe z.B. gcc manpage). Generell, muss man alle anderen Bibliotheken gegen die man linken moechte explizit angeben.

Warum die libm nicht in der libc enthalten ist hat historische Gruende die ich jetzt nicht ausfuehren moechte.

Desshalb muss man wenn die math.h genutzt wird mit -lm gelinkt werden. $ ldd ./a.out

       linux-vdso.so.1 (0x00007fff1a3fc000)
       libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5b6af83000)
       libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5b6abdb000)
       /lib64/ld-linux-x86-64.so.2 (0x00007f5b6b286000)

Wichtig ist jedoch das es sich hierbei um keinen Fehler oder ungewoehnliches Verhalten handelt. Die meisten C Compiler Verhalten sich so. Ich hoffe die kurze und sehr Oberflaechliche Erklaerung, tut nicht mehr fragen auf als sie beantwortet.

Ganz gute Referenzen sind: Learn Linux, 101: Manage shared libraries Introduction to GCC Learning the GNU development Tools