xcode ld: 8 duplicate symbols for architecture x86

2019-03-02 07:20发布

问题:

I am making a game in xcode and c++ with GLUT & OpenGL. I want to place a 3D model in my game and this is the general look of the header file:

unsigned int GunNumVerts = 37812;

float GunVerts [] = {
// f 1/1/1 1582/2/1 4733/3/1
 0.266494348503772, 0.0252334302709736, -0.000725898139236535,
0.265592372987502, 0.0157389511523397, -0.000725898139236535,
0.264890836474847, 0.0182004476109518, -0.00775888079925833,}
float GunNormals [] = {
// f 1/1/1 1582/2/1 4733/3/1
0.986904930120225, -0.0937549933614904, -0.131257990706016,
0.986904930120225, -0.0937549933614904, -0.131257990706016,
0.986904930120225, -0.0937549933614904, -0.131257990706016,}
float GunTexCoords [] = {
// f 1/1/1 1582/2/1 4733/3/1
0.110088, 0.229552,
0.108891, 0.243519,
0.119508, 0.240861,}

I am getting this error with it:

duplicate symbol _GunNumVerts in: /blah/blah/blah/Mouse.o
/blah/blah/blah/ViewPort.o
ld: 8 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I am trying to display this in my display method in my viewport as follows:

glVertexPointer(3, GL_FLOAT, 0, GunVerts);
glNormalPointer(GL_FLOAT, 0, GunNormals);
glTexCoordPointer(2, GL_FLOAT, 0, GunTexCoords);
glDrawArrays(GL_TRIANGLES, 0, GunNumVerts);

I have 7 other duplicate symbol little phrases but there is only one actual error.

回答1:

You defined your variables in the header. That way each variable is present in every (8) compilation units. Instead declare the variables in the header and define them in a .cpp file.

For example:

// Gun.h:
extern unsigned int GunNumVerts;
extern float GunVerts[9];


// Gun.cpp:
unsigned int GunNumVerts;
float GunVerts[9] = {
    // f 1/1/1 1582/2/1 4733/3/1
    0.266494348503772, 0.0252334302709736, -0.000725898139236535,
    0.265592372987502, 0.0157389511523397, -0.000725898139236535,
    0.264890836474847, 0.0182004476109518, -0.00775888079925833};

extern tells the compiler that the adress of the variable is resolved later (by the linker). Also, if you never intend to change these values at runtime they should be declared as const.

/Edit: since you are using clang which has a very good C++11 support, you could also use constexpr for these values. Then they only reside in the header. However, understanding the linker is important for a C++ developer so the original advice stays.