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
Mache nen gescheitet Prototyp für Function1. Liefert die nun int oder void? Johann
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
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?)
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.
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 ********
1 | #ifndef HEADER_H_INCLUDED
|
2 | #define HEADER_H_INCLUDED
|
3 | |
4 | struct TestStruct |
5 | {
|
6 | int Test; |
7 | };
|
8 | |
9 | // Prototypendeklaration
|
10 | extern Function1(struct TestStruct*); |
11 | |
12 | #endif
|
Jetzt kannst du header.h in einer Compilation Unit sooft includieren (direkt oder indirekt) wie du willst oder wie es sich eben ergibt.
... solange er jetzt nicht HEADER_H_INCLUDED in jeder Headerdatei nimmt; eine gewisse Variation von Datei zu Datei wäre hilfreich :-))
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
1 | In file included from ../../provider/soap/soapH.h:10, |
2 | from SOAPUtils.h:39, |
3 | from SOAPUtils.cpp:42: |
4 | ../../provider/soap/soapStub.h:921: error: redefinition of ‘struct user’ |
5 | /usr/include/sys/user.h:50: error: previous definition of ‘struct user’ |
6 | SOAPUtils.cpp: In function ‘ECRESULT CopyUserDetailsToSoap(unsigned int, objectdetails_t, soap*, user*)’: |
7 | SOAPUtils.cpp:1913: error: ‘struct user’ has no member named ‘ulUserId’ |
8 | SOAPUtils.cpp:1914: error: ‘struct user’ has no member named ‘lpszUsername’ |
9 | SOAPUtils.cpp:1915: error: ‘struct user’ has no member named ‘ulIsNonActive’ |
10 | SOAPUtils.cpp:1916: error: ‘struct user’ has no member named ‘lpszMailAddress’ |
11 | SOAPUtils.cpp:1917: error: ‘struct user’ has no member named ‘lpszFullName’ |
12 | SOAPUtils.cpp:1918: error: ‘struct user’ has no member named ‘ulIsAdmin’ |
13 | SOAPUtils.cpp:1919: error: ‘struct user’ has no member named ‘lpszPassword’ |
14 | SOAPUtils.cpp: In function ‘ECRESULT CopyUserDetailsFromSoap(user*, objectdetails_t*, soap*)’: |
15 | SOAPUtils.cpp:1928: error: ‘struct user’ has no member named ‘lpszUsername’ |
16 | SOAPUtils.cpp:1929: error: ‘struct user’ has no member named ‘lpszUsername’ |
17 | SOAPUtils.cpp:1931: error: ‘struct user’ has no member named ‘lpszMailAddress’ |
18 | SOAPUtils.cpp:1932: error: ‘struct user’ has no member named ‘lpszMailAddress’ |
19 | SOAPUtils.cpp:1934: error: ‘struct user’ has no member named ‘ulIsAdmin’ |
20 | SOAPUtils.cpp:1935: error: ‘struct user’ has no member named ‘ulIsAdmin’ |
21 | SOAPUtils.cpp:1937: error: ‘struct user’ has no member named ‘ulIsNonActive’ |
22 | SOAPUtils.cpp:1938: error: ‘struct user’ has no member named ‘ulIsNonActive’ |
23 | SOAPUtils.cpp:1940: error: ‘struct user’ has no member named ‘lpszFullName’ |
24 | SOAPUtils.cpp:1941: error: ‘struct user’ has no member named ‘lpszFullName’ |
25 | SOAPUtils.cpp:1943: error: ‘struct user’ has no member named ‘lpszPassword’ |
26 | SOAPUtils.cpp:1944: error: ‘struct user’ has no member named ‘lpszPassword’ |
27 | make[3]: *** [SOAPUtils.lo] Error 1 |
28 | make[3]: Leaving directory `/root/download/zarafa-6.20.7/provider/common' |
29 | make[2]: *** [all-recursive] Error 1 |
30 | make[2]: Leaving directory `/root/download/zarafa-6.20.7/provider' |
31 | make[1]: *** [all-recursive] Error 1 |
32 | make[1]: Leaving directory `/root/download/zarafa-6.20.7' |
33 | 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
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"?
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.
> 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
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 :-)
> 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?
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
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...
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.
Super vielen dank für die ausführliche Antwort damit komme ich nun zurecht Vielen Dank dafür
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)
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:
1 | # 43 "Src/Lib/Inc/board.h" 2 |
2 | |
3 | |
4 | # 1 "/usr/local/lib/gcc/avr/4.3.2/../../../../avr/include/avr/io.h" 1 3 |
5 | # 99 "/usr/local/lib/gcc/avr/4.3.2/../../../../avr/include/avr/io.h" 3 |
6 | # 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.
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.