2013-09-21 19 views
5

Ich versuche, ein C++ - Projekt in Xcode 4.6.3 zu erstellen.Zufällige doppelte Symbole in xcode (C++)

In meinem Projekt (die Anfänge einer sehr einfachen OpenGL-Spiel) Ich habe zwei Dateien:

textures.h:

#pragma once 

#include <GLUT/GLUT.h> 

void load(); // load textures 

GLuint dirt, water; // variables to store texture handles 

textures.cpp:

#include "textures.h" 

#include "util.h" 

void textures::load() { 
    dirt = util::loadTexture("/Some/Path/Soil.png"); 
    water = util::loadTexture("/Some/Path/Water_fresh.png"); 
} 

Hier definiert util.h die Funktion util :: loadTexture.

Es gibt zwei Dateien, die textures.h enthalten. Die erste (main.cpp) ruft die Funktion load() als Teil der Initialisierung auf und greift auf die Dirt-Variable zu, um die Textur Soil.png zu binden. Die zweite (Chunk.cpp) enthält textures.h, hat aber noch keinen Zugriff darauf.

Wenn ich versuche, das Projekt zu erstellen, es gibt mir die folgende Fehlermeldung:

duplicate symbol _dirt in: 
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/main.o 
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/Chunk.o 
duplicate symbol _water in: 
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/main.o 
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/Chunk.o 
duplicate symbol _dirt in: 
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/main.o 
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/textures.o 
duplicate symbol _water in: 
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/main.o 
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/textures.o 
ld: 4 duplicate symbols for architecture x86_64 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 

Ich verstehe, dass dies bedeutet, dass es ein Duplikat irgendwo ist, oder ein Header mehrfach enthalten. Aber alle meine Header verwenden #pragma once, und ich habe Suche im Arbeitsbereich für "Schmutz" und so getan, und es gibt keine anderen Definitionen. Meine anderen Header funktionieren gut, sogar die, die mehrfach enthalten sind. Ich habe dieses Problem viele Male mit anderen Schlüsselwörtern gegooglet und habe mir ähnliche Fragen angesehen, aber alles, was ich gefunden habe, war this SO question.

Ich habe andere "zufällige" Fehler zuvor in Xcode gefunden - zum Beispiel versuchte ein Projekt, eine dynamische Bibliothek zu verwenden, die ich gelöscht und durch eine statische ersetzt hatte. Der Fehler ist geblieben, selbst als ich ein brandneues Projekt erstellt habe. Es funktionierte, wenn es manuell vom Terminal kompiliert wurde.

Was fehlt mir?

Antwort

5

#pragma once stoppt nicht eine Header-Datei, die mehrfach enthalten ist.

Es stoppt eine Header-Datei wird mehrfach enthalten beim Kompilieren einer einzigen Datei. Sie haben (mindestens) drei Dateien, also deklarieren Sie dieselben Variablen dreimal.

Setzen Sie keine Variablendefinitionen in eine Headerdatei. Tun Sie dies stattdessen

// textures.h 
extern GLuint dirt, water; // variable declarations 


// textures.cpp 
GLuint dirt, water; // variable definitions 

Sie können so viele Erklärungen einer Variablen, wie Sie wollen (vorausgesetzt, sie sind alle gleich), so dass es in Ordnung ist, Deklarationen in einer Header-Datei zu setzen, müssen Sie genau eine Variable Definition haben, so Sie legen das in eine CPP-Datei.

Der Schlüssel zum Erinnern ist, dass jede CPP-Datei vollständig unabhängig von jeder anderen CPP-Datei kompiliert wird. Dies wird als separate Kompilierung bezeichnet. Ihre Idee, dass #pragma once verhindern würde, dass eine Headerdatei in einer .cpp-Datei enthalten ist, nur weil sie in eine andere CPP-Datei aufgenommen wurde, funktioniert einfach nicht. Du bist nicht der erste, der das missversteht.

+0

Ich habe bereits versucht, #pragma einmal für die #ifndef #define #endif ersetzen, die Xcode zunächst erstellt, und es hat immer noch nicht funktioniert ... – qxz

+0

Nun #ifndef ...funktioniert genau so wie #pragma einmal und versäumt es zu tun, was es aus dem gleichen Grund tun sollte. Was ich gepostet habe, ist kein Tipp, es ist die korrekte Art, globale Variablen zu verwenden. – john

+0

Hören Sie nicht auf, #pragma einmal oder #ifndef zu verwenden ... es löst nur ein anderes Problem von dem, was Sie denken, dass es tut. – john