PDA

View Full Version : XCode: Multiple Definitions of Symbol




guest42
Jul 12, 2007, 12:23 AM
Hey all. I am having an infuriating problem with my code. About a month ago I began to program a game in C with openGL, and XCode was great for getting started. However I stopped working on it for weeks until this morning, and for some reason it suddenly is not wanting to compile, giving me a 'multiple definitions' error for a constant float in on of my header files, even though I did a #ifndef-#define-#endif thing.

In a simplest case scenario, the project is a Carbon Application with three classes: main.c, util.h, and util.c, that look like the following:

main.c:

#include "futil.h"

int main(void) {
return 0;
}

util.h:

#ifndef TEST
#define TEST

const float mat = 100.8/45.0; //it tries to define this twice, I guess

#endif

util.c:

#include "util.h"


And that's it. It just doesn't like that constant float, when it didn't have a problem with it a month ago. The error looks something like:
multiple definitions of _mat
If I remove util.c's include, and it's only included once, it works.

I tried fixing this by taking out the constant and code that uses it, but then it came up with a bunch of nonsensical 'undefined' errors for seemingly random things. I even tried installing an older version of XCode, and then in frustration I reinstalled the entire OS thinking that some update had effed things up, but it's doing the same thing.

So on one hand, that tells me it's the code, but on the other hand, it compiled last month just fine, and those compiler directives seem like they ought to keep that variable from being defined twice. Am I missing something! I'd really like to get back to making this game, and I'm crushed that the code isn't working now. Any help would be deeply appreciated.



HiRez
Jul 12, 2007, 12:55 AM
What happens if you change the name "mat" to something else? Or if you do:

#define MAT 100.8/45.0

guest42
Jul 12, 2007, 01:32 AM
Well, I did that, and it worked! It turns out the undefined errors it picked up afterwards were indeed my own doing. What I want to know though is why it would have compiled before if it doesn't like constants declared in that manner. I can only suppose that previously I had never cleaned my work space, and that somehow screwed things up, but I am only speculating. I suppose from now on if I want a constant variable I'll just define it with the compiler.

But could you explain the nature of constants for me, and how they could cause this problem?

In any case, thanks for your help :)

GothicChess.Com
Jul 12, 2007, 04:34 AM
Well, I did that, and it worked! It turns out the undefined errors it picked up afterwards were indeed my own doing. What I want to know though is why it would have compiled before if it doesn't like constants declared in that manner. I can only suppose that previously I had never cleaned my work space, and that somehow screwed things up, but I am only speculating. I suppose from now on if I want a constant variable I'll just define it with the compiler.

But could you explain the nature of constants for me, and how they could cause this problem?

In any case, thanks for your help :)

You defined it as a constant, yet you executed a formula. It is best to either:

A. Make it a variable.
B. Compute the constant, then declare it as its explicit value. That is, don't trust the compiler :)
C. Use a #define to creat a pre-compiled instance of it, which basically overrides whatever will come next in the code.

lazydog
Jul 12, 2007, 06:18 AM
Hi
Did you switch your build from development to release?

You are actually defining multiple definitions of mat. Every time a compilation unit includes util.h it is declaring the variable mat. So in your example, main.c and util.c both declare the variable mat hence the error.

The #defines do guard against multiple inclusions but not across compilation units. For example, if main.c inludes main.h and util.h, and in addition main.h also includes util.h, then the #defines stop util.h being processed twice. This is different from the case where main.c and util.c both include util.h.

In general I think it is much better practise to use const instead of #defines.

b e n

iSee
Jul 12, 2007, 06:41 AM
yeah, lazydog is right.

Your header should declare but not define mat:

util.h#ifndef TEST
#define TEST

const float mat; // declare mat, not define it: no assignment here

#endif

You can then define mat, just once, in util.c:
#include "util.h"

const float mat = 100.8/45.0; // defined only once, right here.

guest42
Jul 12, 2007, 06:43 AM
I see what you are saying lazydog, about it 'mostly' protecting it, until it's sitting in two different implemented files. I suppose that's just one of the limitations of the C compiler. But now that I know this, it's not a big deal. I will probably continue to use constants where I can, as opposed to defines, I suppose that for now, what works, works (though I probably should not count on this).

lazydog
Jul 12, 2007, 07:03 AM
guest42, you don't sound entirely confident with using const in this situation! Perhaps it feels a bit dodgy because of you experience of trying to understand why it worked before and not now. I did manage to replicate the problem somewhat by switching between debug and release build mode. In debug mode you example code worked fine, but when I switched to release mode I got the multiple definition error. I'm not sure why it would be the case that the code compiles in debug mode but I suspect it has something to do with zero link and all that clever stuff.


and thanks iSee for actually pointing out the solution.

b e n

Nutter
Jul 12, 2007, 07:09 AM
Yes, that is Zerolink, may it rest in peace...