Forum: PC-Programmierung Merkwüdiger Fehler: Mal fehlt powl, mal nicht


von Erwin M. (nobodyy)


Lesenswert?

Bei dem C-Programm unten habe ich das Problem das mir die Powl-Funktion 
fehlt, mit der gcc-Fehlermeldung undefined reference to `__powl_finite'.
Ersetze ich powl durch pow kommt die Fehlermeldung mit pow statt powl.

Ersetze ich aber in der langen Kommentar-Zeile die 2 durch eine 0, ist 
der Fehler weg, nur nützt mir das nichts da ich ja etwas berechnen will 
und Variablen brauche und auch Werte ungleich Null brauche.

Andere Funktionen sind problemlos, beispielsweise expl(u/10.0).

Was ist denn an dem Programm falsch?
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <math.h>
4
5
long double ald_2ghzband[3][11] =
6
  { {1.809, 5.682, 17.811, 43.310, 88.722, 148.010, 235.005,
7
     349.170, 477.430, 659.485, 887.470},
8
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
9
{4.037, 12.702, 34.399, 70.238, 126.286, 200.485, 299.975, 427.445, 594.675,
10
 802.725, 1063.620}
11
};
12
13
long double
14
calc_power (const long double y)
15
{
16
17
  if (y < ald_2ghzband[1][0])  
18
    {
19
      return 2; ///////////////////////////////////////////////////////
20
    }
21
  return 0;
22
}
23
24
int
25
main (int argc, char *argv[])
26
{
27
  long double y = 0, u = 0, v = 0;
28
  char **endptr = &(argv[1]) + 10;
29
30
  if (argc < 2)
31
    return (-1);
32
  y = strtold (argv[1], endptr);
33
34
  u = calc_power (y);    
35
  u += 20.0;      
36
  v = powl (10.0, u / 10.0);  
37
  printf ("%.2Lf %.1Lf  %.1Lf\n", y, v, u);
38
  return (0);
39
}

von Rolf M. (rmagnus)


Lesenswert?

Erwin Meyer schrieb:
> Bei dem C-Programm unten habe ich das Problem das mir die Powl-Funktion
> fehlt, mit der gcc-Fehlermeldung undefined reference to `__powl_finite'.

Wie sehen denn dein Comnpiler- und Linker-Aufruf aus? Bei mir geht das 
ohne Probleme durch Compiler und Linker.

Erwin Meyer schrieb:
> Ersetze ich aber in der langen Kommentar-Zeile die 2 durch eine 0, ist
> der Fehler weg

Klar. Dan der Wert von u ja immer gleich, und somit kann das Ergebnis 
schon vom Compiler ausgerechnet werden.

von heinz (Gast)


Lesenswert?

hat jetzt nichts mit deinem Fehler zu tun aber,

>return 2;
>u += 20.0;
>u / 10.0

wieso nicht
return 2.2
bzw.
return 2.0

von Yalu X. (yalu) (Moderator)


Lesenswert?

-lm vergessen?

von Erwin M. (nobodyy)


Lesenswert?

Yalu X. schrieb:
> -lm vergessen?

Nein, ich compiliere mit

gcc -lm -Wall -o tmp tmp.c

Und das Problem mit fehlendem powl habe ich auch bei Programmen, die 
sich vor 12 Jahren problemlos compilieren ließen!

Als funktionierenden Workaround nehme ich erstmal

v = expl(u*logl(10.0)/10.0);

aber es darf kein Dauerzustand sein das plötzlich grundlegende 
Funktionen weg sind, die vor Jahrzehnten noch da waren und seit mehreren 
Jahrzehnten zum C-Standard gehören.
Das Problem habe ich unter Ubuntu 12.04 (64 Bit), aber NICHT unter SuSE 
12.3 (32 Bit).

von Rene H. (Gast)


Lesenswert?

Was sagt nm auf libm.so? Sind da die angemeckerten Symbole drin?

Grüsse,
R.

von Rene H. (Gast)


Lesenswert?

Ich habe das schnell bei mir getestet. Funktioniert 1a. SLES 11 (64 
Bit)/gcc 4.3.4

Kann es sein, das auf Deinem System die libm zerschossen ist? Hast Du 
auch mal die 64bit Variante versucht?

Grüsse,
R.

von Tobi (Gast)


Lesenswert?

Funktioniert prima mit

gcc test.c -o test -lm -Wall

Ubuntu Precise 64Bit, gcc 4.6.3

Gruss,
Tobi

von Erwin M. (nobodyy)


Lesenswert?

Rene H. schrieb:
> Was sagt nm auf libm.so? Sind da die angemeckerten Symbole drin?
>
> Grüsse,
> R.

Also vorhanden ist die

/usr/lib/x86_64-linux-gnu/libm.so

als Link letztlich auf die libm-2.15.so und nm meldet dazu "no symbols". 
Aber das kann es zumindest allein nicht sein, denn auf einem anderen 
Rechner, unter Debian, ist es ebenso obwohl powl dort vorhanden ist.

von Rene H. (Gast)


Lesenswert?

Erwin Meyer schrieb:
> als Link letztlich auf die libm-2.15.so und nm meldet dazu "no symbols".
> Aber das kann es zumindest allein nicht sein, denn auf einem anderen
> Rechner, unter Debian, ist es ebenso obwohl powl dort vorhanden ist.

Hmmm.... bei mir sieht das so aus:

$:~> nm /lib/libm-2.11.1.so | grep powl
0001afe0 t __cpowl
000160c0 t __ieee754_powl
00018940 t __powl
0001afe0 W cpowl
00018940 W powl

no symbols klingt für mich nicht sehr gut.

Grüsse,
R.

von Malte (Gast)


Lesenswert?

Erwin Meyer schrieb:
> Nein, ich compiliere mit
>
> gcc -lm -Wall -o tmp tmp.c

Das -lm an das Ende der Zeile setzen.

von Erwin M. (nobodyy)


Lesenswert?

Malte schrieb:
> Erwin Meyer schrieb:
>> Nein, ich compiliere mit
>>
>> gcc -lm -Wall -o tmp tmp.c
>
> Das -lm an das Ende der Zeile setzen.

Unglaublich aber damit geht es, danke!
Aber das ist nur unter Ubuntu nötig; unter Debian geht es mit -lm vorne, 
obwohl es beides 64-Bit-PCs mit dem gcc 4.6.3 sind.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Was mich auch noch etwas wundert:

Erwin Meyer schrieb:
> undefined reference to `__powl_finite'.

Es soll also nicht die powl-, sondern die abgespeckte
__pow-finite-Funktion eingebunden werden. Das passiert aber
normalerweise nur dann, wenn man gcc mit einer der Optionen
-ffinite-math-only oder -ffast-math aufruft. Beides scheint bei dir
nicht der Fall zu sein:

Erwin Meyer schrieb:
> gcc -lm -Wall -o tmp tmp.c

Oder ist bbei dir gcc ein Alias oder ein Skript, das evtl. noch
weitere Optionen übergibt, die in der Befehlszeiche nicht sichtbar sind?

Rene H. schrieb:
> $:~> nm /lib/libm-2.11.1.so | grep powl
> 0001afe0 t __cpowl
> 000160c0 t __ieee754_powl
> 00018940 t __powl
> 0001afe0 W cpowl
> 00018940 W powl
>
> no symbols klingt für mich nicht sehr gut.

Bei mir muss ich noch -D (für dynamic) angeben. Das Ergebnis sieht dann
so aus (nm 2.23.2):
1
$ nm -D /lib/libm-2.17.so |grep powl
2
0000000000037d20 T __powl_finite
3
000000000003d990 W cpowl
4
000000000003aad0 W powl

Es sind also beide Varianten (powl und __powl_finite) vorhanden.

In deiner libm scheint aber das fragliche __powl_finite tatsächlich zu
fehlen (vielleicht weil deine libm schon etwas älter ist), was aber kein
Problem sein sollte, wenn man ohne -ffast-math kompiliert.

@Erwin:

Poste doch mal die Versionsnummern von gcc, nm und libm. Da scheint es
ja deutliche Unterschiede zwischen den einzelnen Versionen zu geben. Und
probier mal nm -D zum Auflisten der Symbole in libm.so.

Was mich nach wie vor wundert, dass die Sache bei dir mit

> v = expl(u*logl(10.0)/10.0);

funktioniert.

Was passiert eigentlich, wenn du bei diesem Workaround das -lm weglässt?
Wird dann expl oder __expl_finite vermisst?

von Malte (Gast)


Lesenswert?

Erwin Meyer schrieb:
> Unglaublich aber damit geht es, danke!
> Aber das ist nur unter Ubuntu nötig; unter Debian geht es mit -lm vorne,
> obwohl es beides 64-Bit-PCs mit dem gcc 4.6.3 sind.

Das mit -lm vorne hin schreiben ist neumodischer Sch**ssdr*ck. Seit 
Anbeginn der Zeit (1.1.1970) schreibt man das hinten hin.

Ein anständiger Unix-Linker arbeitet die Argumente in einem Durchgang in 
der Reihenfolge ab in der sie auf der Kommandozeile angegeben werden. Er 
sucht nur nach den Symbolen die beim aktuellen Stand des Linkens 
benötigt werden. Schreibt man -lm vorne hin, wird die libm zuerst 
abgearbeitet, zu einem Zeitpunkt, an dem noch gar keine Symbole benötigt 
werden. Daher interessiert den Linker nicht, was in der libm ist.

Steht -lm hinten, hat der Linker schon tmp.o gesehen wenn er zu libm 
kommt, und tmp.o verlangt halt nach ein paar Symbolen, die libm 
"zufällig" hat.

Irgendwann sind so ein paar neumodische Hippster, die mit dem Konzept 
"Reihenfolge wie auf der Kommandozeile" mental völlig überfordert waren 
(ja, Latte saufen macht dumm), hingegangen und haben sich irgendwas 
zusammengehackt, das die Reihenfolge irgendwie nicht mehr so richtig 
gilt. Manchmal. Vielleicht. An Sommertagen. Sehr "lustig", wenn man 
statt gegen eine Standardfunktion gegen eine eigene Implementierung mit 
gleichem Namen linken will :-(

von Erwin M. (nobodyy)


Lesenswert?

Yalu X. schrieb:

> Oder ist bbei dir gcc ein Alias oder ein Skript, das evtl. noch
> weitere Optionen übergibt, die in der Befehlszeiche nicht sichtbar sind?

Nein, which sagt zum gcc /usr/bin/gcc und das ist ein Link auf das 
Programm /usr/bin/gcc-4.6.


> Bei mir muss ich noch -D (für dynamic) angeben. Das Ergebnis sieht dann
> so aus (nm 2.23.2):
> $ nm -D /lib/libm-2.17.so |grep powl
> 0000000000037d20 T __powl_finite
> 000000000003d990 W cpowl
> 000000000003aad0 W powl
>
> Es sind also beide Varianten (powl und __powl_finite) vorhanden.

Ja, bei mir auch.


> Poste doch mal die Versionsnummern von gcc, nm und libm. Da scheint es
> ja deutliche Unterschiede zwischen den einzelnen Versionen zu geben. Und
> probier mal nm -D zum Auflisten der Symbole in libm.so.

gcc: 4.6.3
nm: 2.22
libm: 2.15


> Was mich nach wie vor wundert, dass die Sache bei dir mit
>
>> v = expl(u*logl(10.0)/10.0);
>
> funktioniert.
>
> Was passiert eigentlich, wenn du bei diesem Workaround das -lm weglässt?
> Wird dann expl oder __expl_finite vermisst?

Ja, klar.
Was mich wunderte ist das meine Shell-Funktion, die ich seit so 10 
Jahren zum Compilieren (+strippen) verwende, plötzlich nicht mehr 
funktioniert, weil das -lm nicht ganz am Ende der gcc-Optionen steht. 
Hinzu kam verwirrenderweise, das es mit speziellen Werte doch noch ging. 
Nach dem Umstellen, also -lm ganz nach hinten, geht es wieder.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Erwin Meyer schrieb:
>> Was passiert eigentlich, wenn du bei diesem Workaround das -lm weglässt?
>> Wird dann expl oder __expl_finite vermisst?
>
> Ja, klar.

Meine Frage war schlecht formuliert. Ich meinte eigentlich: Welche der
beiden Funktionen wurde als "undefined reference" gemeldet?

Aber nachdem jetzt alles funktioniert, ist das im Prinzip ja auch egal.

von Erwin M. (nobodyy)


Lesenswert?

Yalu X. schrieb:
> Erwin Meyer schrieb:
>>> Was passiert eigentlich, wenn du bei diesem Workaround das -lm weglässt?
>>> Wird dann expl oder __expl_finite vermisst?
>>
>> Ja, klar.
>
> Meine Frage war schlecht formuliert. Ich meinte eigentlich: Welche der
> beiden Funktionen wurde als "undefined reference" gemeldet?
>
> Aber nachdem jetzt alles funktioniert, ist das im Prinzip ja auch egal.

Achso; ohne -lm werden powl bzw. expl als fehlend gemeldet.
Wie oben beschrieben wird mit -lm unter den mittleren Optionen nur powl 
bemängelt, mit __powl_finite, und expl geht problemlos; das ist so 
gerade auf der Kippe und geht noch halb - zumindest mit expl.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.