1

I have a simple program using FreeGLUT, OpenGL, and some nice simplex noise functions from Eliot Eshelman. The goal is to display 2D slices some 3D simplex noise, which I've managed with SDL.

My problem is: I'm getting multiple definition errors that I can't seem to resolve.

I've searched around on Google and these forums for a while. I learned about quite a few things that could cause errors, BUT I can't seem to find the cause of mine. I've been stumped by these errors for many hours.

Here's my relevant sources and error outputs.

Note that there could be more bugs past the errors I'm getting, but I haven't been able to debug far enough to get to them yet.

Output:

-------------- Build: Release in OpenGL Test (compiler: GNU GCC Compiler)---------------

mingw32-g++.exe -Wall -O2 -std=c++11 -IC:\freeglut\include -c "C:\OpenGL Test\OpenGL Test\main.cpp" -o obj\Release\main.o
mingw32-g++.exe -LC:\freeglut\lib -o "bin\Release\OpenGL Test.exe" obj\Release\LUtil.o obj\Release\main.o obj\Release\simplexnoise.o  -s -lmingw32 -lOpenGL32 -lglu32 -lfreeglut   -mwindows
obj\Release\main.o:main.cpp:(.bss+0x0): multiple definition of `textureName'
obj\Release\LUtil.o:LUtil.cpp:(.bss+0x0): first defined here
obj\Release\main.o:main.cpp:(.bss+0x20): multiple definition of `noiseImage'
obj\Release\LUtil.o:LUtil.cpp:(.bss+0x20): first defined here
obj\Release\main.o:main.cpp:(.bss+0x12c020): multiple definition of `zOffset'
obj\Release\LUtil.o:LUtil.cpp:(.bss+0x12c020): first defined here
collect2.exe: error: ld returned 1 exit status
Process terminated with status 1 (0 minute(s), 0 second(s))
0 error(s), 0 warning(s) (0 minute(s), 0 second(s))

LUtil.h:

/*This source code copyrighted by Lazy Foo' Productions (2004-2013)
and may not be redistributed without written permission.*/
//Version: 001

#ifndef LUTIL_H
#define LUTIL_H

#include "LOpenGL.h"

#include "simplexnoise.h"

//Screen Constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_FPS = 60;

float zOffset = 0;

float noiseImage[640][480];

GLuint textureName;

bool initGL();
/*
Pre Condition:
 -A valid OpenGL context
Post Condition:
 -Initializes matrices and clear color
 -Reports to console if there was an OpenGL error
 -Returns false if there was an error in initialization
Side Effects:
 -Projection matrix is set to identity matrix
 -Modelview matrix is set to identity matrix
 -Matrix mode is set to modelview
 -Clear color is set to black
*/

void update();
/*
Pre Condition:
 -None
Post Condition:
 -Does per frame logic
Side Effects:
 -None
*/

void render();
/*
Pre Condition:
 -A valid OpenGL context
 -Active modelview matrix
Post Condition:
 -Renders the scene
Side Effects:
 -Clears the color buffer
 -Swaps the front/back buffer
*/

#endif

LUtil.cpp:

/*This source code copyrighted by Lazy Foo' Productions (2004-2013)
and may not be redistributed without written permission.*/
//Version: 001

#include "LUtil.h"

bool initGL()
{
    //Initialize Projection Matrix
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();

    //Initialize Modelview Matrix
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    //Initialize clear color
    glClearColor( 0.f, 0.f, 0.f, 1.f );

    //Check for error
    GLenum error = glGetError();
    if( error != GL_NO_ERROR )
    {
        printf( "Error initializing OpenGL! %s\n", gluErrorString( error ) );
        return false;
    }

    glGenTextures(1, &textureName);
    glBindTexture(GL_TEXTURE_2D, textureName);

    return true;
}

void update()
{
    for(int y = 0; y < SCREEN_HEIGHT; y++)
    {
        for(int x = 0; x < SCREEN_WIDTH; x++)
        {
                noiseImage[x][y] = raw_noise_3d(x, y, zOffset);
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCREEN_WIDTH, SCREEN_HEIGHT, 0, GL_RGB, GL_FLOAT, &noiseImage[0][0]);
        }
    }
}

void render()
{
    //Clear color buffer
    glClear( GL_COLOR_BUFFER_BIT );

    glColor4f(1, 0.5f, 0, 1);

    //Render quad
    glBegin( GL_QUADS );
        glTexCoord2f(  -1.f, -1.f );
        glTexCoord2f(  -1.f,  1.f );
        glTexCoord2f( 1.f,  -0.f );
        glTexCoord2f( 1.f,  1.f );
    glEnd();

    //Update screen
    glutSwapBuffers();
}

main.cpp:

/*This source code copyrighted by Lazy Foo' Productions (2004-2013)
and may not be redistributed without written permission.*/
//Version: 001

#include "LUtil.h"

void runMainLoop( int val );
/*
Pre Condition:
 -Initialized freeGLUT
Post Condition:
 -Calls the main loop functions and sets itself to be called back in 1000 / SCREEN_FPS milliseconds
Side Effects:
 -Sets glutTimerFunc
*/

int main( int argc, char* args[] )
{
    //Initialize FreeGLUT
    glutInit( &argc, args );

    //Create OpenGL 2.1 context
    glutInitContextVersion( 4, 4 );

    //Create Double Buffered Window
    glutInitDisplayMode( GLUT_DOUBLE );
    glutInitWindowSize( SCREEN_WIDTH, SCREEN_HEIGHT );
    glutCreateWindow( "OpenGL" );

    //Do post window/context creation initialization
    if( !initGL() )
    {
        printf( "Unable to initialize graphics library!\n" );
        return 1;
    }

    //Set rendering function
    glutDisplayFunc( render );

    //Set main loop
    glutTimerFunc( 1000 / SCREEN_FPS, runMainLoop, 0 );

    //Start GLUT main loop
    glutMainLoop();

    return 0;
}

void runMainLoop( int val )
{
    //Frame logic
    update();
    render();

    //Run frame one more time
    glutTimerFunc( 1000 / SCREEN_FPS, runMainLoop, val );
}

As far as I can tell, there are no multiple definitions, but I could be wrong. Once again, I'm sorry if I'm "That guy" with this question.

Willy Goat
  • 1,175
  • 2
  • 9
  • 24
  • 4
    As a rule of thumb, you don't want to define variables (or objects) in .h files. Like `GLuint textureName;` if you have to use globals like that, then define them in their relevant .cpp file then use `extern` to declare them in other files. – mbadawi23 Sep 16 '14 at 00:22
  • 1
    You should learn the difference between a **declaration** and a **definition**. – Code-Apprentice Sep 16 '14 at 00:25
  • 1
    The double include should not be a problem, since it seems to have the proper #ifndef . But indeed, the definitions that cause the warnings should not be in .h file. – Pieter21 Sep 16 '14 at 00:28
  • 2
    See Code-Apprentice's answer. As for the #ifdef, that only prevents you from including it directly or indirectly twice in the **same** module(source file). However it can be included in separate modules (which you did) which in turn created multiple non-static copies of the variables in question – Michael Petch Sep 16 '14 at 00:30
  • Goodness, my inexperience shows. Thank you. – Willy Goat Sep 16 '14 at 00:35
  • possible duplicate of [c++ multiple definitions of a variable](http://stackoverflow.com/questions/11072244/c-multiple-definitions-of-a-variable) – Reto Koradi Sep 16 '14 at 00:55

1 Answers1

7

Move the definitions of your global variabls to LUtil.cpp:

float zOffset = 0;

float noiseImage[640][480];

GLuint textureName;

Then declare the variabls in LUtil.h:

extern float zOffset;

extern float noiseImage[640][480];

extern GLuint textureName;
Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268