1

While compiling C (not c++) code, I am getting error during link time, that certain identifiers have been defined at multiple places, but as shown below, the output is very cryptic.

Is there a way to get better messages from gcc, so that I can see which files are the cause of multiple definitions?

/tmp/cc8kgsLE.o:(.rodata+0x0): multiple definition of `PR_SZ'
/tmp/ccDfv6U4.o:(.rodata+0x0): first defined here
/tmp/cc8kgsLE.o:(.rodata+0x8): multiple definition of `PR_SEC_SZ'
/tmp/ccDfv6U4.o:(.rodata+0x8): first defined here
/tmp/cc8kgsLE.o:(.rodata+0x10): multiple definition of `PR_NSEC_SZ'
/tmp/ccDfv6U4.o:(.rodata+0x10): first defined here

collect2: ld returned 1 exit status

UPDATE: Based on responses, i clarify further that PR_SZ, PR_SEC_SZ, PR_NSEC_SZ are defined in ONE .h file, which is protected by #ifndef, #define and #endif macros..

In terms of compiling, i simply type:

gcc -Wall -I. -file1.c file2.c -o file2

UPDATE:

In addition to responses, i found the below link relevant global constants without using #define

Community
  • 1
  • 1
Jimm
  • 8,165
  • 16
  • 69
  • 118

2 Answers2

4

The output displayed doesn't look cryptic for me, it's very clear... The globals variables (this is bad) PR_SZ, PR_SEC_SZ, PR_NSEC_SZ are defined into more than one .c files

How do you compile your project ?

Here the main problem, it's that .o filename doesn't match the filename of the .c file. So to be able to see a better message you should improve your Makefile or whatever you are using to build your project.

For information :

  • In .h the prototype of global variables declarations must be prefixed by the keyword : extern
  • In only one .c file the variable should be declare normally
benjarobin
  • 4,410
  • 27
  • 21
  • They also could be defined in one source file only. Typically in an `.h` file which then in turn is included by more then one `.c` file. The comment on the OP made by *simonc* is a way worth going. – alk Dec 17 '12 at 17:37
  • they are defined in only one .h file. This .h file is included by .c files. i have made sure to protect .h file with #ifndef , #define and #endif macros. In terms of compiling i am simply writing gcc -Wall file1.c file2.c -o file2 – Jimm Dec 17 '12 at 17:39
  • 1
    The declaration into the `.h` must use external, if this is not the case, this is just bad coding... – benjarobin Dec 17 '12 at 17:39
  • I thought it's `extern`. Does `external` also do? – alk Dec 17 '12 at 17:44
  • 3
    @Jimm #ifndef will prevent them from multiple includes in the same .c file. However, if the are being included in multiple .c files, then it will lead to the same var being defined multiple times. – user93353 Dec 17 '12 at 17:45
  • @user93353 i do include same .h file across multiple .c files. But i include across multiple .c and it does not complain. So are you sure that #ifndef does not protect across .c files? – Jimm Dec 17 '12 at 17:47
  • Yes we are sure, gcc compile independently each .c file. Do not mix up, prototype declaration and variable declaration – benjarobin Dec 17 '12 at 17:48
  • @benjarobin this is not a compile error, rather a link error. During linking, does #ifndef not protect across multiple .o files? Given my stdio.h file being included in multiple.c files, how come gcc does not complain for it? – Jimm Dec 17 '12 at 17:50
  • There are no globals in `stdio.h`. @Jimm – alk Dec 17 '12 at 17:50
  • 1
    The linker don't know anything about the language, the linker don't read source code, it doesn't event know what a .c source code is, only gcc understand it – benjarobin Dec 17 '12 at 17:51
  • 1
    Macros are applied even before compiling, during pre-processing! @Jimm – alk Dec 17 '12 at 17:51
  • @Jimm what global variables does `stdio.h`contain? – user93353 Dec 17 '12 at 17:54
  • @user93353 stderr, stdin, stdout – Jimm Dec 17 '12 at 17:55
  • @Jimm: Regarding pre-processing you might like to have look a this answer (although answering a differnt question it might help to enlight ;-)): http://stackoverflow.com/a/13517652/694576 – alk Dec 17 '12 at 17:56
  • stdio.h doesn't declare any global variable !!! It only provide the prototype of the variable : `extern struct _IO_FILE *stderr;` – benjarobin Dec 17 '12 at 17:56
  • @Jimm: Verbatim from `stdio.h`: `extern struct _IO_FILE *stderr; ` Please note the use of the key word `extern`! – alk Dec 17 '12 at 17:57
2

You can do this.

In the header file

/* a.h */
MYEXTERN int PR_SZ; /* or whatever your variable data type is */

In the first .c file

/* a.c */
/* MYEXTERN doesn't evaluate to anything, so var gets defined here */
#define MYEXTERN 
#include "a.h"

In the other .c files

/* MYEXTERN evaluates to extern, so var gets externed in all other C files */
#define MYEXTERN extern
#include "a.h"

So it gets defined in only one .c file & gets externed in all the others.

user93353
  • 13,733
  • 8
  • 60
  • 122
  • Looks complicated, so why would you do this? – alk Dec 17 '12 at 17:59
  • Yes this is a solution... Used a lot in industry. But maybe this is too complicate to understand for a beginner. This is used when there are a lot of global variable to declare and it's prevent to have different prototype between .c and .h file – benjarobin Dec 17 '12 at 18:00
  • The gain : Prevent errors... Think about this case : In the .c file you declare the variable as char, and in the .h an int. What do you think it's may happen ? – benjarobin Dec 17 '12 at 18:03
  • One more reason to not use (lots) of global variables. – alk Dec 17 '12 at 18:05
  • In embedded software in some case you don't really have the choice... But yes global variable is bad, and should not be used. – benjarobin Dec 17 '12 at 18:06
  • @benjarobin global constants are not bad – Jimm Dec 17 '12 at 18:18
  • In this case use #define or if you cannot use the keywords : const + static in the .h : It will use more memory... But you don't need to declare the variable in the .c file – benjarobin Dec 17 '12 at 18:34