Repeated Multiple Definition Errors from including same header in multiple cpps

Wolerywol picture Wolerywol · Oct 22, 2008 · Viewed 37.9k times · Source

So, no matter what I seem to do, I cannot seem to avoid having Dev C++ spew out numerous Multiple Definition errors as a result of me including the same header file in multiple source code files in the same project. I'd strongly prefer to avoid having to dump all my source code into one file and only include the header once, as that's going to make my file very long and difficult to manage.

Essentially, this is what's going on:

#ifndef _myheader_h
#define _myheader_h

typedef struct MYSTRUCT{
int blah;
int blah2; } MYSTRUCT;

MYSTRUCT Job_Grunt;
MYSTRUCT *Grunt = &Job_Grunt;
MYSTRUCT Job_Uruk;
MYSTRUCT *Uruk = &Job_Grunt;

int Other_data[100];

void load_jobs();

#endif

Example Cpp File (They pretty much all look something like this):

#include "myheader.h"

void load_jobs(){

Grunt->blah = 1;
Grunt->blah2 = 14;

Uruk->blah = 2;
Uruk->blah2 = 15;

return; }

Bear in mind that I have about 5 cpp files that include this one header, each one dealing with a different type of struct found in the header file. In this example there was only the one struct containing a couple of members, when there are about 4-6 different structs with many more members in the actual header file. All the files I've included it in follow the same formula as you see in this example here.

Now I understand that the header guard only stops each individual cpp file from including the header file more than once. What would seem to be happening is that when the compiler reads the include at the start of each cpp, it defines the header file all over again, which is causing it to spit out lines and lines of:

Multiple Definition of Uruk, first defined here  
Multiple Definition of Job_Uruk, first defined here  
Multiple Definition of Grunt, first defined here  
Multiple Definition of Job_Grunt, first defined here  
Multiple Definition of Other_data, first defined here

I'll see a set of this for just about every cpp file in the project which includes the header. I've tried moving the definitions of the struct and the struct variables to the cpp files, but then the other cpp files cannot see them or work with them, which is very important as I need all files in the project to be able to work with these structs.

But the single most confusing part about this problem requires a little more explanation:

The way I'm setting up these multiple files in this project is identical to the book I'm working with, All In One Game Programming by John S. Harbour. I ran into the exact same problems when I created the files for example projects in the book which called for one header included by multiple cpps in the same project.

I could type them out, word for word from the book, and I do mean word for word...
and I'd get the series of MD errors for every cpp in the project.

If I loaded the example project from the CD included with the book, it would compile and run without a problem, allthough the files themselves, as well as the project options, were by all appearances identical to the ones I had created.

If I created my own project file, and simply added the source and header files for the example project from the CD, this, too, would also compile and run, though I can find no difference between those and mine.

So then, I tried making my own project file, then creating the blank source and header files and adding them to it, and then filling them by copying and pasting their contents from the files on the CD they were meant to correspond to(the same ones that had worked). And sure enough, I'd get the same thing...lines and lines of MD error messages.

I'm absolutely baffled. I've repeated all these methods multiple times, and am certain I'm not mistyping or miscopying the code. There just seems to be something about the premade files themselves; some configuration setting or something else I'm missing entirely...that will cause them to compile correctly while the files I make myself won't.

Answer

Head Geek picture Head Geek · Oct 22, 2008

Since you're declaring those variables in the header file, and including the header file in each C++ file, each C++ file has its own copy of them.

The usual way around this is to not declare any variables within header files. Instead, declare them in a single C++ file, and declare them as extern in all the other files that you might need them in.

Another way I've handled this before, which some people might consider unpleasant... declare them in the header file, like this:

#ifdef MAINFILE
    #define EXTERN
#else
    #define EXTERN extern
#endif

EXTERN MYSTRUCT Job_Grunt;
EXTERN MYSTRUCT *Grunt = &Job_Grunt;
EXTERN MYSTRUCT Job_Uruk;
EXTERN MYSTRUCT *Uruk = &Job_Uruk;

Then, in one of your C++ files, add a...

#define MAINFILE

...before your #include lines. That will take care of everything, and is (in my personal opinion) a lot nicer than having to redeclare all of the variables in every file.

Of course, the real solution is not to use global variables at all, but when you're just starting out that's hard to achieve.