0

I get the following errors when I'm trying to build my c code files with -D. But, if I build it without -D, it works. I don't know why. Thanks. (My machine is ubuntu12.10, 32bit)

gcc c1.c c2.c -D DEBUG

/tmp/ccX04EIf.o:(.data+0x0): multiple definition of `g'
/tmp/cc0j9MoU.o:(.data+0x0): first defined here
collect2: ld returned 1 exit status

Here is my source code:

global.h

#ifdef DEBUG 
    int g = 23;
    static int init = 1;
#else
    int g;
    static int init = 0;
#endif

c1.c

#include "global.h"
int f() {
    return g + 1;
}

c2.c

#include <stdio.h>
#include "global.h"

int main() {
    if (!init) {
        g = 37;
    }
    int t = f();
    printf("calling f yields %d\n", t);

    return 0;
}
Suma
  • 33,181
  • 16
  • 123
  • 191
qiaoba
  • 5
  • 1
  • 3

2 Answers2

3

You define the variable g in the header file, that means it will be defined in all source files that includes the header file.

Instead declare it, like

extern int g;

and then define it in a single source file.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • or add include guards? – How Chen Oct 25 '13 at 07:18
  • @HowChen Include guards only protects against multiple inclusion in a single translation unit (e.g. source file), not against multiple inclusion in multiple translation units. – Some programmer dude Oct 25 '13 at 07:21
  • @JoachimPileborg I understand what you mean. Now I change global.h to make sure there is only declaration of g, and move the g definition into c2.c when DEBUG is defined. It works. Thank you. – qiaoba Oct 25 '13 at 08:05
1

The difference between the two code paths (with and without DEBUG) is the initialization of the g variable. Without it, it is only a "tentative" definition, and so the symbol is only generated in the file that really uses it, namely c2.o.

With initialization it is a real definition of the symbol, and so it is also generated in c1.o.

As a rule of thumb, header files should never contain data definitions, only declarations. Data "declarations-only" should be made with the keyword extern. You'd then need to define any such symbol in exactly one of your .c files.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177