Forum: Compiler & IDEs Problem mit Inline in header


von TM F. (p_richner)


Lesenswert?

Hallo zusammen

Ich habe in C eine Inline Definierung in einem Header.
Im main.c habe ich das Headerfile eingebunden. Wenn ich jedoch 
kompilieren will, zeigt es mir an, dass es mehrmals definiert ist. 
Verschiebe ich die Definition jedoch ins main.c, ist der Code 
kompilierbar.

Danke für Lösungsansätze.

MfG

: Verschoben durch User
von Peter II (Gast)


Lesenswert?

TM F. schrieb:
> Danke für Lösungsansätze.

in den Fehlermeldung steht doch do, wo es mehrfach vorhanden ist.

Include guard vorhanden?

von TM F. (p_richner)


Lesenswert?

Peter II schrieb:
> in den Fehlermeldung steht doch do, wo es mehrfach vorhanden ist.

Es zeigt mir nicht an, wo weitere Definitionen sind und wenn ich die 
Namen ändere, bleiben die Fehlermeldungen.

: Bearbeitet durch User
von Sebastian V. (sebi_s)


Lesenswert?

Alter Compiler der noch kein richtiges inline kann? Deine Fehlermeldung 
ist vom Linker nehm ich mal an?

von Peter II (Gast)


Lesenswert?

TM F. schrieb:
> Es zeigt mir nicht an, wo weitere Definitionen sind und wenn ich die
> Namen ändere, bleiben die Fehlermeldungen.

dann zeige uns doch mal die Fehlermeldung

von TM F. (p_richner)


Angehängte Dateien:

Lesenswert?

Peter II schrieb:
> dann zeige uns doch mal die Fehlermeldung

Hier

von Peter II (Gast)


Lesenswert?

TM F. schrieb:
> Hier

kann du den text nicht mal ohne bild posten, am besten sogar wo man die 
erste spalte vollständig sieht?

von Jay (Gast)


Lesenswert?

Wie soll man da wirklich was sehen? Ok, der Compiler sagt definition, 
nicht declaration, also vielleicht wie Peter II schrieb:

Peter II schrieb:
> Include guard vorhanden?

von N. G. (newgeneration) Benutzerseite


Lesenswert?

Vllt meint man:
static inline
Damit wird die Funktion nicht an den linker weitergereicht

von Sebastian V. (sebi_s)


Lesenswert?

Die Fehlermeldungen sind offensichtlich vom Compiler also wirds ein 
Problem wegen fehlender Include Guards sein.

von Karl H. (kbuchegg)


Lesenswert?

Sebastian V. schrieb:
> Die Fehlermeldungen sind offensichtlich vom Compiler also wirds ein
> Problem wegen fehlender Include Guards sein.

Nop
multiple definition" ist immer vom Linker.

Da fehlt ein 'static' vorm 'inline'.

Ohne wird der Compiler auf jeden Fall auch eigenständige 
Implementierungen für die Funktionen erzeugen, weil er nicht davon 
ausgehen kann, dass sie quer durch das Programm überall geinlined 
werden.
Mit static kann er davon ausgehen, dass dem so ist.

von TM F. (p_richner)


Lesenswert?

Karl H. schrieb:
> Da fehlt ein 'static' vorm 'inline'.

Genau, dies hat mein Problem gelöst :)

Danke für die Hilfe

von Sebastian V. (sebi_s)


Lesenswert?

Karl H. schrieb:
> Nop
> multiple definition" ist immer vom Linker.
>
> Da fehlt ein 'static' vorm 'inline'.

Ah hab mich von den Zeilennummern verwirren lassen. Wenn man nicht mit 
Debug Informationen Compiliert kriegt man nicht so schön Ausgaben.

Trotzdem ist es ein merkwürdiger Fehler vom Compiler. Inline Funktionen 
im Header sind korrekt und sollten auch ohne static davor compilieren 
(tun sie bei mir auch).

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


Lesenswert?

Sebastian V. schrieb:
> Trotzdem ist es ein merkwürdiger Fehler vom Compiler.

Nein.  C99-Semantik.

von Karl H. (kbuchegg)


Lesenswert?

Sebastian V. schrieb:
> Karl H. schrieb:
>> Nop
>> multiple definition" ist immer vom Linker.
>>
>> Da fehlt ein 'static' vorm 'inline'.
>
> Ah hab mich von den Zeilennummern verwirren lassen. Wenn man nicht mit
> Debug Informationen Compiliert kriegt man nicht so schön Ausgaben.
>
> Trotzdem ist es ein merkwürdiger Fehler vom Compiler. Inline Funktionen
> im Header sind korrekt und sollten auch ohne static davor compilieren
> (tun sie bei mir auch).

Compilieren tun sie.
Das ist auch nicht das Problem.

Aber: da der Compiler nicht davon ausgehen kann, dass an allen Stellen 
geinlined wird, muss er auch eine freistehende Defintion dieser Funktion 
erstellen. Du könntest dich ja aus einem ganz anderen C-File mittels 
explizitem 'extern' auf diese Funktion beziehen.

Ein 'static' davor begrenzt aber den Scope dieser Funktion auf jeden 
Fall auf das C-File, in welches diese inline Definition hineingezogen 
wurde. D.h. in diesem Fall ist es prinzpiell nicht möglich, dass sich 
irgendwelcher anderer Code mittels 'extern' auf diese Funktion beziehen 
könnte. Der Compiler kennt weiss also, dass in diesem Fall er beim 
Compilieren dieses einen C-Files alle Stellen gesehen hat, an der diese 
Funktion benutzt wurde. Und da er die alle geinlined hat, braucht es die 
freistehende Funktion nicht.

main.c
1
extern void bar();
2
3
inline void foo()
4
{
5
  mach was ....
6
}
7
8
int main()
9
{
10
  foo();   // dieser Aufruf wird geinlined
11
  bar();
12
}

help.c
1
extern void foo();
2
3
void bar
4
{
5
  foo();   // aber dieser Aufruf nicht. Daher muss es neben der
6
           // direkten Ersetzung in main.c auch noch eine tatsächlich
7
           // aufrufbare Version der Funktion geben.
8
}

Das ist das eigentliche Problem, wie es dazu kommt, dass der Compiler 
bei jedem #include (mit den inline-Funktionen) in jeder Compilation-Unit 
eine weitere Version der Funktion erzeugen muss.

Und nochmal:
Der Fehler stammt nicht vom Compiler sondern vom Linker, der bei der 
Endmontage der Einzelteile bemerkt, dass es eine (tatsächliche) Funktion 
dieses Namens ein paar mal gibt. In jedem C-File, welches vom Compiler 
einzeln übersetzt wurde, sind dieselben Funktionen jedesmal als 
tatsächlich aufrufbare Funktionen erneut angelegt worden.

: Bearbeitet durch User
von Sebastian V. (sebi_s)


Lesenswert?

Jörg W. schrieb:
> Nein.  C99-Semantik.

Sicher? Ich habe gerade nochmal rumgespielt und ich kann das Problem vom 
TO nur nachvollziehen wenn ich mit -std=gnu89 compiliere. Mit -std=c99 
und -std=c11 erhalte ich statt "multiple definition" ein "undefined 
reference to" Fehler beim Linken.

Der C99 Standard sagt dazu:
If all of the file scope declarations for a function in a translation 
unit include the inline function specifier without extern, then the 
definition in that translation unit is an inline definition. An inline 
definition does not provide an external definition for the function, 
[...]

Wenn ich das richtig verstehe, dann besagen diese Zeile das in dem Fall 
vom TO, also nur inline im Header, KEINE externe Definition 
bereitgestellt wird und ich damit auch keinen "multiple definition" 
Fehler kriege. Stattdessen kriege ich "undefined reference to" weil gar 
nichts extern definiert wird, sofern man das nicht einmal explizit 
macht.

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


Lesenswert?

Sebastian V. schrieb:
> An inline definition does not provide an external definition for the
> function, [...]

Stimmt, dann hab' ich das verwechselt.  Karl-Heinz hat die Erklärung
ja geliefert.

von Sebastian V. (sebi_s)


Lesenswert?

Karl Heinz behauptet aber auch, dass bei jeder inline Definition eine 
externe Definition erzeugt wird:

Karl H. schrieb:
> Das ist das eigentliche Problem, wie es dazu kommt, dass der Compiler
> bei jedem #include (mit den inline-Funktionen) in jeder Compilation-Unit
> eine weitere Version der Funktion erzeugen muss.

Das scheint aber auch nur auf die GNU 89 Variante von C zuzutreffen.

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


Lesenswert?

Sebastian V. schrieb:
> Das scheint aber auch nur auf die GNU 89 Variante von C zuzutreffen.

Ja, schließlich war ‘inline’ in C89 selbst noch nicht definiert,
erst in C99.

Jedenfalls ist man mit ‘static inline’ immer auf der sicheren Seite.
Wenn der Compiler die Funktion nicht inline auflöst, verplempert man
allerdings Platz.

von B. S. (bestucki)


Lesenswert?

Jörg W. schrieb:
> Wenn der Compiler die Funktion nicht inline auflöst, verplempert man
> allerdings Platz.

Mit -Winline wird man vom GCC gewarnt, falls dies der Fall ist.

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.