www.mikrocontroller.net

Forum: Compiler & IDEs struct an Funktionübergeben "error: redefinition of 'struct XYZ'


Autor: Ludwig (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen

in meinem Projekt ist die folgende Situation:

// Globale Struct deklaration
struct TestStruct
{
 int Test;
};

// Prototypendeklaration
extern Function1(struct TestStruct*);

void Function1(struct TestStruct *Struct2)
{
[...]
}

// Main funktion
int main()
{
   struct TestStruct Struct1;
   Function1(&Struct1);
}


Beim compilieren bekomme ich gleich in der 1. Zeile den folgenden 
Fehler:
"error: redefinition of 'struct TestStruct'"

Allerdings ist das ganze sonst nirgends mehr definiert ?!?
Woran kann das denn liegen?

Danke für eure Hilfe.
Gruß,
Ludwig

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mache nen gescheitet Prototyp für Function1. Liefert die nun int oder 
void?

Johann

Autor: Ludwig (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, war nur ein tipfehler beim schreiben des Beitrags.

der Prototyp lautet natürlich

extern void Function1(struct TestStruct*);

Aber an dem liegts ja nicht

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
die erste Zeile ist Kommentar, an der kann's ja kaum liegen.

Ansonsten kann ich es kompilieren, also hast du wahrscheinlich
noch irgendwas unterschlagen.

Gibt es einen ganzen Quelltext und komplette Fehlermeldungen?
Am besten auch die Fehlermeldungen zu dem Quelltext?
(Wenn du beim Abtippen Fehler gemacht hast, hast du ja wohl
etwas anderes kompiliert als hier steht?)

Autor: Ludwig (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Antwort.

Ich hab mit sicherheit was anderes kompiliert als da steht, da es sich 
dabei nur um eine Auszug handelt.

Hab den Fehler aber gefunden, denn die struct definition stand in einer 
Header Datei, die versehentlich 2mal eingebunden war.

-> redefinition.

Also Problem gelöst.
Passt.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ludwig schrieb:
> Danke für die Antwort.
>
> Ich hab mit sicherheit was anderes kompiliert als da steht, da es sich
> dabei nur um eine Auszug handelt.
>
> Hab den Fehler aber gefunden, denn die struct definition stand in einer
> Header Datei, die versehentlich 2mal eingebunden war.

Dagegen sichert man sich mit einem Include Guard ab

header.h
********
#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED

struct TestStruct
{
 int Test;
};

// Prototypendeklaration
extern Function1(struct TestStruct*);

#endif

Jetzt kannst du header.h in einer Compilation Unit sooft includieren 
(direkt oder indirekt) wie du willst oder wie es sich eben ergibt.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... solange er jetzt nicht HEADER_H_INCLUDED in jeder Headerdatei nimmt;
eine gewisse Variation von Datei zu Datei wäre hilfreich :-))

Autor: Benjamin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe ein ähnliches Problem auf ner arm CPU
Ich wollte Zarafa (eine Groupware) übersetzen auf x86 läuft der make 
durch auf dem sheevaplug habe ich allerdings folgende error meldung
In file included from ../../provider/soap/soapH.h:10,
                 from SOAPUtils.h:39,
                 from SOAPUtils.cpp:42:
../../provider/soap/soapStub.h:921: error: redefinition of ‘struct user’
/usr/include/sys/user.h:50: error: previous definition of ‘struct user’
SOAPUtils.cpp: In function ‘ECRESULT CopyUserDetailsToSoap(unsigned int, objectdetails_t, soap*, user*)’:
SOAPUtils.cpp:1913: error: ‘struct user’ has no member named ‘ulUserId’
SOAPUtils.cpp:1914: error: ‘struct user’ has no member named ‘lpszUsername’
SOAPUtils.cpp:1915: error: ‘struct user’ has no member named ‘ulIsNonActive’
SOAPUtils.cpp:1916: error: ‘struct user’ has no member named ‘lpszMailAddress’
SOAPUtils.cpp:1917: error: ‘struct user’ has no member named ‘lpszFullName’
SOAPUtils.cpp:1918: error: ‘struct user’ has no member named ‘ulIsAdmin’
SOAPUtils.cpp:1919: error: ‘struct user’ has no member named ‘lpszPassword’
SOAPUtils.cpp: In function ‘ECRESULT CopyUserDetailsFromSoap(user*, objectdetails_t*, soap*)’:
SOAPUtils.cpp:1928: error: ‘struct user’ has no member named ‘lpszUsername’
SOAPUtils.cpp:1929: error: ‘struct user’ has no member named ‘lpszUsername’
SOAPUtils.cpp:1931: error: ‘struct user’ has no member named ‘lpszMailAddress’
SOAPUtils.cpp:1932: error: ‘struct user’ has no member named ‘lpszMailAddress’
SOAPUtils.cpp:1934: error: ‘struct user’ has no member named ‘ulIsAdmin’
SOAPUtils.cpp:1935: error: ‘struct user’ has no member named ‘ulIsAdmin’
SOAPUtils.cpp:1937: error: ‘struct user’ has no member named ‘ulIsNonActive’
SOAPUtils.cpp:1938: error: ‘struct user’ has no member named ‘ulIsNonActive’
SOAPUtils.cpp:1940: error: ‘struct user’ has no member named ‘lpszFullName’
SOAPUtils.cpp:1941: error: ‘struct user’ has no member named ‘lpszFullName’
SOAPUtils.cpp:1943: error: ‘struct user’ has no member named ‘lpszPassword’
SOAPUtils.cpp:1944: error: ‘struct user’ has no member named ‘lpszPassword’
make[3]: *** [SOAPUtils.lo] Error 1
make[3]: Leaving directory `/root/download/zarafa-6.20.7/provider/common'
make[2]: *** [all-recursive] Error 1
make[2]: Leaving directory `/root/download/zarafa-6.20.7/provider'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/root/download/zarafa-6.20.7'
make: *** [all] Error 2

Wenn ich es richtig deute wird die user.h doppelt eingebunden.
Aber wieso klappt es auf nem x86
Meine Erfahrungen mit c++ sind etwas verstaubt. Ich steh etwas auf dem 
schlauch Das Desgin ist Little Endian und ich kompiliere direkt auf dem 
arm. Also ist es kein Cross-Compile Problem

Autor: Benjamin Andreas (hagelsturm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe mich mal angemeldet vermute das Problem ist etwas komplex kann 
mir jemand erklären wie der inculde-guard funktioniert reicht da ein 
einfaches "extern"?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Benjamin schrieb:

> ../../provider/soap/soapStub.h:921: error: redefinition of ‘struct user’
> /usr/include/sys/user.h:50: error: previous definition of ‘struct user’

> Wenn ich es richtig deute wird die user.h doppelt eingebunden.

Ich würde die Compilerausschrift so deuten, dass sowohl soapStub.h
als auch user.h eine struct user definieren.  Sehr wahrscheinlich
definieren beide noch dazu eine komplett verschiedene.  Da wird
dir wohl oder übel nicht viel übrig bleiben (sofern du beide
Headerdateien wirklich brauchst), als eine von beiden umzubenennen.

Autor: Benjamin Andreas (hagelsturm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich würde die Compilerausschrift so deuten, dass sowohl soapStub.h
> als auch user.h eine struct user definieren.  Sehr wahrscheinlich
> definieren beide noch dazu eine komplett verschiedene.  Da wird
> dir wohl oder übel nicht viel übrig bleiben (sofern du beide
> Headerdateien wirklich brauchst), als eine von beiden umzubenennen.

Vielen Dank für die Antwort reicht es ein

mv /usr/include/sys/user.h /usr/include/sys/user.h_old zu machen oder 
muß ich im Code die User.h auszukommentieren
Das Problem ist die User.h wird irgendwie indirekt eingebunden ein grep 
-i auf das Verzeichnis hat mir bis jetzt nicht viel gebracht.
Aber mühsam ernährt sich das Eichhörnchen :-)
Ich bin neu auf dem Gebiet bitte entschuldigt die Frage

Autor: Benjamin Andreas (hagelsturm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay ich glaube ich versteh was du meinst muß nur noch die richtigen 
Stellen im Code finde da stocher ich momentan noch etwas rum für Tipps 
bin ich jederzeit dankbar :-)

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Vielen Dank für die Antwort reicht es ein
>
> mv /usr/include/sys/user.h /usr/include/sys/user.h_old zu machen oder

Das ist ganz übler Pfusch!


Welchen Teil von Jörgs Antwort

> Ich würde die Compilerausschrift so deuten, dass sowohl
> soapStub.h als auch user.h eine struct user definieren.

hast Du jetzt eigentlich nicht verstanden?

Autor: Benjamin Andreas (hagelsturm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das das nicht umbedingt sauber ist weiß ich :-)

ich finde halt nur die Stelle im c-Code nicht.
ich stocher wiegesagt  drin rum aber das wird schon hoffe
Ich suche halt die richtige Stelle im code um den Header umzubenennen
ich hab ein find über die source gemacht und das dann gegrept bis jetzt 
habe ich nicht die Stelle gefunden wo User.h eingebunden wird

das ist mein Problem

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Benjamin Andreas schrieb:

> Ich suche halt die richtige Stelle im code um den Header umzubenennen
> ich hab ein find über die source gemacht und das dann gegrept bis jetzt
> habe ich nicht die Stelle gefunden wo User.h eingebunden wird

Dann wuerde ich mal nach user.h suchen statt nach User.h.

> Meine Erfahrungen mit c++ sind etwas verstaubt.

Ist wohl die Untertreibung des Jahrhunderts...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Benjamin Andreas schrieb:
> Das das nicht umbedingt sauber ist weiß ich :-)
>
> ich finde halt nur die Stelle im c-Code nicht.
> ich stocher wiegesagt  drin rum aber das wird schon hoffe
> Ich suche halt die richtige Stelle im code um den Header umzubenennen
> ich hab ein find über die source gemacht und das dann gegrept bis jetzt
> habe ich nicht die Stelle gefunden wo User.h eingebunden wird

Das ist letztendlich auch ziemlich egal.
Nimm zb die user.h her

* sieh nach ob du include guards drinnen hast
* benenne die struct um

Wirf den Compiler über alles drüber und wenn du nicht allzuviel Pech 
hast kommt der Compiler selber drauf welche Files und welche Funktionen 
du an den geänderten struct Namen anpassen musst. Warum? Weil er 
plötzlich die Member der ursprünglichen struct im Duplikat nicht mehr 
finden wird.

In der Funktion, die der Compiler anmäkelt tauscht du dann ebenfalls den 
struct Namen, auf die Funktionsargumente nicht vergessen, die 
zugehörigen Protoypen nicht vergessen und auf gehts zur nächsten 
Compilerrunde. Das machst du solange, bis wieder alles sauber 
compiliert.

Der Compiler führt dich durch die notwendigen Änderungen, wenn du einer 
struct einen anderen Namen verpasst.

Autor: Benjamin Andreas (hagelsturm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Super vielen dank für die ausführliche Antwort damit komme ich nun 
zurecht

Vielen Dank dafür

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du darfst allerdings klarerweise die Compiler-Fehlermeldungen nicht für 
bare Münze nehmen. Du weißt ja, dass alle Fehler nur dadurch verursacht 
sind, dass die struct jetzt einen anderen Namen hat. Jede einzelne 
Fehlermeldung ist daher im Grunde nur der Hinweis: Irgendwo vorher muss 
es eine struct Variable geben oder einen Pointer auf eine struct, in der 
jetzt der falsche struct Name drinnen steht. Ein bischen mitdenken muss 
man also, so ganz automatisch gehts nicht.

Und verlier auch nicht zuviel Zeit mit Folgefehlern. Wenn du deine 
Fehlerliste durchgehst, die kann durchaus am Anfang des Prozesses ein 
paar Hundert Fehler umfassen, dann arbeite nicht alle Fehler durch. Nimm 
dir die ersten paar vor und drück dann auf "compile". Mit jedem 'Fehler' 
den du ausbaust, werden auch eine Unmenge an Folgefehler verschwinden 
(und manchmal ein paar neue Fehlermeldungen dazukommen)

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für hartnäckige Fälle, bei denen man partout nicht finden kann,
wer denn nun das #include <sys/user.h> dort verbrochen hat, kann
man sich die Ausgaben des Präprozessors ansehen.  Dazu benutzt
man die Option -E (statt -c), die Ausgabe landet entweder auf
stdout (kann man nach "more" oder "less" weiterleiten) oder aber
in der per -o benannten Datei.

Darin finden sich dann solche Dinge wieder:
# 43 "Src/Lib/Inc/board.h" 2


# 1 "/usr/local/lib/gcc/avr/4.3.2/../../../../avr/include/avr/io.h" 1 3
# 99 "/usr/local/lib/gcc/avr/4.3.2/../../../../avr/include/avr/io.h" 3
# 1 "/usr/local/lib/gcc/avr/4.3.2/../../../../avr/include/avr/sfr_defs.h" 1 3

Das bedeutet, dass ab Zeile 43 in Src/Lib/Inc/board.h zwei leere
Zeilen generiert werden (da könnten in der Datei bspw. auch #define
oder #ifdef stehen, denn die werden vom Präprozessor in der Ausgabe
gelöscht), danach wird offenbar <avr/io.h> aufgerufen.  In avr/io.h
springt der Präprozessor dann von Zeile 1 auf Zeile 99 (am Anfang
der Datei liegt ein sehr großer Kommentar, den er entfernt hat), und
auf Zeile 99 wird dann <avr/sfr_defs.h> reingezogen.

Wenn man in einer derartigen Ausgabe das erste Vorkommen von
sys/user.h sucht und von dort rückwärts geht, sollte man herausfinden,
welche Stelle in welcher Datei das zugehörige #include enthält.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:

> Das ist letztendlich auch ziemlich egal.
> Nimm zb die user.h her

Das ist natürlich Quatsch.
Da die user.h aus dem sys Zweig ist, lässt du die klarerweise in Ruhe.
Du änderst den Namen der struct im anderen Header File.

Das restliche Vorgehen bleibt dasselbe, wobei noch ein Hinweis auf die 
Fähigkeiten des Editors erfolgen soll:
Replace im File, wobei sinnigerweise 'whole word only' und 'respect 
case' eingeschaltet werden sollte, sofern vorhanden.

Autor: Benjamin Andreas (hagelsturm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe die struct  umbenannt war eigenlich recht simple nochmal vielen 
dank für die super erklärung
hat super geklappt warum der Fehler aufm arm auftritt und auf nem x86 
nicht bleibt mir zwar ein Rätsel aber nun habe ich fertige Arm Binarys

P.s das make hat 2 stunden gdauert das nächste mal compiliere ich lieber 
cross auf ner CPU mit ordentlich FPU :-)

Nochmal Danke

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.