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


von Ludwig (Gast)


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

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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

Johann

von Ludwig (Gast)


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

von Klaus W. (mfgkw)


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?)

von Ludwig (Gast)


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.

von Karl H. (kbuchegg)


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
********
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.

von Klaus W. (mfgkw)


Lesenswert?

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

von Benjamin (Gast)


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
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

von Benjamin A. (hagelsturm)


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"?

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


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.

von Benjamin A. (hagelsturm)


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

von Benjamin A. (hagelsturm)


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 :-)

von Rufus Τ. F. (rufus) Benutzerseite


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?

von Benjamin A. (hagelsturm)


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

von P. S. (Gast)


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...

von Karl H. (kbuchegg)


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.

von Benjamin A. (hagelsturm)


Lesenswert?

Super vielen dank für die ausführliche Antwort damit komme ich nun 
zurecht

Vielen Dank dafür

von Karl H. (kbuchegg)


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)

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


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:
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.

von Karl H. (kbuchegg)


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.

von Benjamin A. (hagelsturm)


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

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.