2013-09-21 13 views
5

Sto provando a creare un progetto C++ in Xcode 4.6.3.Simboli di duplicazione casuale in xcode (C++)

Nel mio progetto (l'inizio di un gioco molto semplice OpenGL) Ho due file:

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"); 
} 

Qui util.h definisce la funzione util :: loadTexture.

Ci sono due file che includono tex.h. Il primo (main.cpp) chiama la funzione load() come parte dell'inizializzazione e accede alla variabile dirt per legare la trama Soil.png. Il secondo (Chunk.cpp) include textures.h, ma in realtà non accede ancora a nulla da esso.

Quando provo a costruire il progetto, mi dà il seguente errore:

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) 

Capisco che questo significa che c'è un duplicato da qualche parte, o un colpo di testa è incluso più volte. Ma tutte le mie intestazioni usano #pragma once, e ho fatto ricerche nello spazio di lavoro per "sporco" e così via, e non ci sono altre definizioni. Le mie altre intestazioni funzionano bene, anche quelle che sono incluse più volte. Ho cercato su Google questo problema molte volte con parole chiave diverse e ho dato un'occhiata ad altre domande simili, ma tutto ciò che ho trovato è stato this SO question.

Ho riscontrato altri errori "casuali" in Xcode: ad esempio, un progetto ha cercato di utilizzare una libreria dinamica che avevo cancellato e sostituito con uno statico. L'errore è rimasto, anche quando ho creato un nuovo progetto. Ha funzionato quando compilato manualmente da Terminal.

Cosa mi manca?

risposta

5

#pragma once non interrompe l'inclusione di un file di intestazione più volte.

Arresta un file di intestazione che viene incluso più volte durante la compilazione di un singolo file. Hai (almeno) tre file in modo da dichiarare le stesse variabili 3 volte.

Non inserire le definizioni delle variabili in un file di intestazione. Fate questo invece

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


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

Si può avere il maggior numero di dichiarazioni di una variabile come si desidera (a condizione che siano tutte identiche), quindi è OK per mettere le dichiarazioni in un file di intestazione, si deve avere esattamente una definizione di variabile, in modo da lo metti in un file .cpp.

La chiave da ricordare è che ogni file .cpp viene compilato in modo completamente indipendente da ogni altro file .cpp, questo viene chiamato compilazione separata. Quindi la tua idea che #pragma once possa impedire a un file di intestazione di essere incluso da un file .cpp solo perché è stato incluso in un altro file .cpp, non funziona. Non sei il primo a fraintenderlo.

+0

Ho già provato a sostituire #pragma una volta per #ifndef #define #endif che Xcode inizialmente crea e ancora non ha funzionato ... – qxz

+0

Bene #ifndef ...funziona esattamente come #pragma una volta e non riesce a fare ciò che pensi dovrebbe fare per lo stesso motivo. Quello che ho postato non è un suggerimento, è il modo corretto di usare variabili globali. – john

+0

Non smettere di usare #pragma una volta o #ifndef ... è proprio questo che risolve un problema diverso da quello che pensi che faccia. – john