Forum: Compiler & IDEs inline vs -O0


von hui (Gast)


Lesenswert?

Ich habe in einem Header eine inline-Funktion deklariert.
Ein anderes Modul inkludiert diesen Header und ruft diese Funktion auf.

Im Assembler-Listing sehe ich, dass die Funktion wirklich ge-inlined 
wird.
Da der Compiler auch die Parameter kennt kann sie sogar fast vollständig 
wegoptimiert werden (2 Takte vs 65!).
Mit meiner Lösung bin ich sehr zufrieden.
Wollte allerdings noch testen wie sich das Ganze ohne Optimierung 
verhält.

Allerdings compiliert mir mein Code mit -O0 garnicht erst:
undefined reference to ***
Aktueller avr-gcc.

Hab auf die schnelle nichts gefunden. Aber inline müsste doch auch ohne 
Optimierung erfolgen? (Auch wenns hier wenig sinn macht, nur aus 
Interesse)

von .... (Gast)


Lesenswert?

Bist du hobbymäßiger Ironie-Betreiber??

Deine *** ist exakt das einzige, was aus deinem Post hilfreich gewesen 
wäre.

Oder... du nutzt die Delay-Routinen, aber keine 
Mathe/Floatingpoint-Lib...

Rück raus mit dem Fehler oder es *****

:-P

von Karl H. (kbuchegg)


Lesenswert?

mach eine static inline Funktion draus

von hui (Gast)


Lesenswert?

> Deine *** ist exakt das einzige, was aus deinem Post hilfreich gewesen
wäre.

Was genau hilft dir, wenn du weist das meine Funktion fubarfubar123() 
heißt?

@ Karlheinz: danke, das wars. Aber wieso?

inline sorgt ja dafür, dass ich, bei mehrfachen Einbindungen des 
Headers, keinen redefinition-error bekomme.

Ok, ohne static wird das Symbol auchnoch exportiert, dadurch könnte eine 
andere Kompiliereinheit per "extern" am Header vorbei diese Funktion 
aufrufen. Ohne static muss der Compiler also auch einmal die 
"Vollversion" meiner Funktion anlegen, sie könnte ja wo anders benutzt 
werden. Soweit ist static hier ok!

Aber dieses "undefined reference" kann ich mir nicht erklären.

Leider geistert zu diesem Thema im Netz sehr viel Halbwissen :/

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

hui schrieb:

> inline sorgt ja dafür, dass ich, bei mehrfachen Einbindungen des
> Headers, keinen redefinition-error bekomme.

Nein.  Das macht "static".  "inline" ist nur ein Hinweis an den
Compiler, dass der Entwickler der Meinung war, dass diese Funktion
sinnvoll inline erweiterbar sei.  Der Compiler muss sich dieses
Hinweises nicht annehmen (so, wie früher auch "register" nur ein
Hinweis war).  GCC inlinet die entsprechende Funktion, sofern sie
seiner Meinung nach klein genug ist, und sofern die Optimierungen
zugelassen sind.  Die Idee dabei ist einfach, dass jemand, der
ausdrücklich keine Optimierungen wünscht, in der Regel eine möglichst
gute 1:1-Abbildung seines Quellcodes im Maschinencode sehen möchte.

> Ok, ohne static wird das Symbol auchnoch exportiert, dadurch könnte eine
> andere Kompiliereinheit per "extern" am Header vorbei diese Funktion
> aufrufen.

Ja.

> Ohne static muss der Compiler also auch einmal die
> "Vollversion" meiner Funktion anlegen, sie könnte ja wo anders benutzt
> werden.

Nein.  Nicht der Compiler, sondern du.  Du musst in einer der
Übersetzungseinheiten noch eine ganz normale globale Funktion haben,
auf die der Linker dann zurückgreifen kann.  Woher zum Geier[tm]
sollte denn der Compiler wissen, in welcher deiner vielen
Übersetzungseinheiten er nun gerade die nicht-inline-Implementierung
hinterlassen soll?

Genau diese Implementierung fehlt dir aber jetzt, daher "undefined
reference", denn durch die ausgeschalteten Optimierungen wird die
Funktion ja nicht inline angelegt und stattdessen versuch, auf die
globale Implementierung zurückzugreifen.

von Peter II (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Nein.  Nicht der Compiler, sondern du.  Du musst in einer der
> Übersetzungseinheiten noch eine ganz normale globale Funktion haben,
> auf die der Linker dann zurückgreifen kann.

wenn die funktion in der Header datei als inline implementiert ist, dann 
ist sie doch in jeder Quelle wo die Header-Datei verwendet wird 
enthalten?

Sie würde dann sogar in jeder übersetzungseinheit (wo dieser header 
vorhanden ist) vorhanden sein

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter II schrieb:

> Sie würde dann sogar in jeder übersetzungseinheit (wo dieser header
> vorhanden ist) vorhanden sein

Und, wie soll das gehen, ohne dass der Linker sich dann über
eine Mehrfachdefinition des entsprechenden Namens beschwert?

Ja, der Compiler könnte sie nur entweder in jeder Übersetzungsein-
heit oder in keiner dieser global implementieren.  Sich eine
einzelne auszuwählen, ist ihm mangels geeigneter Kriterien (muss ja
auch nicht alles zur gleichen Zeit compiliert werden) nicht möglich.
Da eine Implementierung in jeder Einheit nicht möglich ist (wegen
der dann auftretenden Mehrfachdefinitionen), bleibt nur die Variante,
sie nirgends automatisch zu generieren, sondern die Entscheidung, wo
er die globale Definition anlegt, dem Programmierer zu überlassen.

Anders bei “static inline”: hier kann der Compiler ohne ein Risiko
von Mehrfachdefinitionen in jeder Übersetzungseinheit eine Kopie
hinterlegen, wenn er die Funktion nicht inline erweitert (und das
tut er auch, was natürlich den Sinn von “inline” ins Gegenteil
verkehrt; man hat dann viel Code, der trotzdem langsam ist).

von hui (Gast)


Lesenswert?

>Und, wie soll das gehen, ohne dass der Linker sich dann über
eine Mehrfachdefinition des entsprechenden Namens beschwert?

Durch das inline?
Zumindest ein kurzer Test hat mich vorhin zu diesem Gedankengang 
bewogen.

Funktion im Header ohne inline: klappt natürlich nicht, redefined
Funktion im Header, mit inline: klappt super!
-O0: undefined reference. Er sucht anscheinend eine Funktion ohne 
inline, deswegen der Fehler

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

hui schrieb:
>>Und, wie soll das gehen, ohne dass der Linker sich dann über
> eine Mehrfachdefinition des entsprechenden Namens beschwert?
>
> Durch das inline?

Du hast das nicht bis zu Ende gedacht.

Unter welchem Namen soll der Compiler denn die N verschiedenen,
nicht inline implementierten Kopien im Objektcode hinterlegen, sodass
der Linker sie alle auflösen kann, es aber keine Mehrfachdefinitionen
gibt?

> Funktion im Header ohne inline: klappt natürlich nicht, redefined
> Funktion im Header, mit inline: klappt super!

Klar, solange er alle inline erweitert.  Bei “extern inline” legt
der Compiler ja keine zusätzliche globale Kopie an (wie wir schon
festgestellt hatten).  Solange er alle Aufrufe inline erweitern
kann, werden diese auch nicht gebraucht.

> -O0: undefined reference. Er sucht anscheinend eine Funktion ohne
> inline, deswegen der Fehler

Ja, die eine globale Kopie muss dann ohne “inline” stehen, logisch.

Also so:

foo.h:
1
inline void foo(void) { PORTB = 42; }

foo.c:
1
#include "foo.h"
2
3
/* das ist die globale Kopie */
4
void foo(void)
5
{
6
  PORTB = 23; /* ja, die kann auch was ganz anderes machen ;-) */
7
}

bar.c:
1
#include "foo.h"
2
3
void dosomething(void)
4
{
5
  /* ... */
6
  foo();  /* mit Optimierung wird foo() inline erweitert, ohne
7
             wird dagegen das foo() aus foo.c gerufen */
8
}

Wenn man sich stets angewöhnt, alle inline-Funktionen “static inline”
zu deklarieren, ist man den Kuddelmuddel los.  Eine “static”
deklarierte Funktion bekommt ja keinen global gültigen Namen, sondern
einen, der nur in der jeweiligen Übersetzungseinheit gültig ist.
Damit gibt es auch dann keine Namenskollision, wenn der Compiler sich
entschließt, das “inline” zu ignorieren.

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.