XCode: Multiple Definitions of Symbol

Discussion in 'Mac Programming' started by guest42, Jul 11, 2007.

  1. macrumors newbie

    Joined:
    Jul 11, 2007
    #1
    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:

    Code:
    #include "futil.h"
    
    int main(void) {
         return 0;
    }
    util.h:

    Code:
    #ifndef TEST
    #define TEST
    
    const float mat = 100.8/45.0; //it tries to define this twice, I guess
    
    #endif
    util.c:

    Code:
    #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:
    Code:
    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.
     
  2. macrumors 601

    HiRez

    Joined:
    Jan 6, 2004
    Location:
    Western US
    #2
    What happens if you change the name "mat" to something else? Or if you do:

    Code:
    #define MAT 100.8/45.0
     
  3. thread starter macrumors newbie

    Joined:
    Jul 11, 2007
    #3
    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 :)
     
  4. macrumors regular

    GothicChess.Com

    Joined:
    Apr 6, 2007
    Location:
    Philadelphia, PA
    #4
    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.
     
  5. macrumors 6502a

    Joined:
    Sep 3, 2005
    Location:
    Cramlington, UK
    #5
    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
     
  6. macrumors 68040

    iSee

    Joined:
    Oct 25, 2004
    #6
    yeah, lazydog is right.

    Your header should declare but not define mat:

    util.h
    Code:
    #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:
    Code:
    #include "util.h"
    
    const float mat = 100.8/45.0; // defined only once, right here.
    
     
  7. thread starter macrumors newbie

    Joined:
    Jul 11, 2007
    #7
    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).
     
  8. macrumors 6502a

    Joined:
    Sep 3, 2005
    Location:
    Cramlington, UK
    #8
    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
     
  9. macrumors 6502

    Joined:
    Mar 31, 2005
    Location:
    London, England
    #9
    Yes, that is Zerolink, may it rest in peace...
     

Share This Page