So I have a source mainClass.c where I have the main defined. I have a header file class1.h and the implementation of all the functions defined in class1.h in class1.c. I have two variables (global) in class1.h named cond and mutex which are being used in class1.c for now and probably in future I will be using it in my mainClass.c as well.
Now to compile all the source files to generate one object file I am doing something as follows:
gcc -Wall -pthread -I/home/2008/ariarad/mainClass1 mainClass1.c class1.c -o out
/home/2008/ariarad/mainClass1 is where all my header and source files are at and I am using pthead.h in one of the .c file. Even though I have included it there it complains so I had to include it.
Now when I run the above command the I get the following errors:
class1.c:3:16: error: redefinition of ‘cond’
class1.h:66:16: note: previous definition of ‘cond’ was here
class1.c:4:17: error: redefinition of ‘mutex’
class1.h:67:17: note: previous definition of ‘mutex’ was here
Just in case I have an ifndef and endif block surrounding the class1.h to avoid multiple inclusion. I am definitely not redefining the variables defined in the header file in the .c file. So can someone please help me why it is still giving me the errors?
You cannot define global variables in header files. You must define them in one of the .c files, and then use extern in the header files:
In one of the .c files:
int cond;
In one of the .h files, which must be included by all .c files that need the variable:
extern int cond;
Related
This question already has answers here:
How do I use extern to share variables between source files?
(19 answers)
Closed 4 years ago.
I have a relatively small project with only a few files (.c and .h). I have been fighting multiple inclusion errors (I think). So, I created a master.h header file that has each of the other header files that are needed. ALL of the header files have the
#ifndef _MY_HEADER
#define _MY_HEADER
… Header body
#endif
guards to prevent multiple inclusion. Each of my files includes the master.h file at the top. Here is how I would expect this to work.
The first file that was compiled would see the #include "master.h"
Since this is the first time that this file is processed __MASTER would not have been defined yet, so it would process the file.
The compiler would come to the inclusion of the next header file, an similarly, it would have not been processed yet, so the complier would process it, then it would be defined, and would not be processed again.
This continues for all the header files in the master.h until all the files have been processed, and defined so they won't be processed again.
The same is true of the master.h file. Once it's processed, and completed, it won't be processed again due to the guard.
Shouldn't this prevent multiple inclusion?
So here are the errors.
Building target: My_Project_Bootloader.axf
Invoking: GNU ARM C Linker
arm-none-eabi-gcc -g3 -gdwarf-2 -mcpu=cortex-m3 -mthumb -T "C:/Users/Greg/SimplicityStudio/v4_workspace/My_Project_Bootloader/GNU ARM v4.9.3 - Debug/My_Project_Bootloader_custom.ld" -nostdlib -L"C:\GCC_STUFF" --specs=nosys.specs -Xlinker --gc-sections -Xlinker -Map="My_Project_Bootloader.map" -lm -lgcc -lc -o My_Project_Bootloader.axf "./Source/aeabi_memset-thumb.o" "./Source/crt0.o" "./Source/em_emu.o" "./Source/functions.o" "./Source/main.o" "./Source/startup_efm32jg1b.o" "./Source/interrupts.o"
./Source/main.o:(.rodata.const_ModBusIDReg+0x0): multiple definition of `const_ModBusIDReg'
./Source/functions.o:(.rodata.const_ModBusIDReg+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
make: *** [My_Project_Bootloader.axf] Error 1
I've edited/removed some of the information in this post because it turns out it is unrelated. It appears that the "multiple definition" problems the linker was having was not due to actual "multiple definitions", or inclusions for any variable. Instead, it appears as if it was due to declaring and defining the variable (in this case a const in flash) at the same time. Once I split the declaration(s) into a header file, and the actual definition or assignment into a .c file, the problems went away. Here is an example of the fix for one of the problem "variables". I will pay much closer attention to the declaration and definition aspects of variables now. The tools used was GCC. Thank you for all the comments.
// boot.h
// declare const array
const unsigned char const_ModBusIDReg[7][48];
// boot.c
#include boot.h
// define const array
const unsigned char const_ModBusIDReg[7][48] =
{
"String1", // reg00
"String2", // reg01
"String3", // reg02
"String4", // reg03
"String5", // reg04
"String6", // reg05
"String7" // reg06
};
Usually #ifndef HEADER_NAME like you did avoid any including conflicts. But you said "Each of my files includes the master.h" so i suggest that your .c should not include anything else than they own associated .h. (It might already be the case).
Also, beware of including .c.
I don't know about your linker script but what tool do you use to compile ?
The problem is a linker issue, not a per source file issue. It won't be solved by stopping headers from being included multiple times in a single translation unit (TU — source file plus included files).
It appears that you have four symbols (const_ModBusIDReg, const_ModBusRegAttr,
const_ModBusRegDefaults,
const_ModBusRegLimits) which are defined in multiple source files, possibly because you define rather than declare them in a header.
Variables cited in a header must be prefixed with extern — otherwise, they are definitions, not declarations.
Is there any Linker option, which enforces error for multiple definition of a function.
I am using ARM GCC mingw.
I am facing problem where if I am using Guard in header file(say A.h) like this
#ifndef H_H_
#define H_H_
and declare function definition inside it
Linker is not giving error for Multiple definitions of that function in different .C files which includes above A.h file
I have a header file with the declaration of several global variables in the following format:
constants.h
#ifndef CONSTANTS_H
#define CONSTANTS_H
extern unsigned var;
EXPORT_SYMBOL(var);
#endif
constants.c
#include "constants.h"
unsigned var = 10;
foo.c
#include "constants.h"
When I try to compile the kernel module, I get the following error for each respective exported symbol:
WARNING: /home/vilhelm/proj/constants: 'var' exported twice. Previous export was in /home/vilhelm/proj/foo.ko
I suspect that the symbols are being exported every time I include the constants.h header file, but I don't understand why. Shouldn't the include guard in constants.h prevent the EXPORT_SYMBOL(var) from being read multiple times?
Shouldn't the include guard in constants.h prevent the
EXPORT_SYMBOL(var) from being read multiple times?
The include guard prevents the header from being included more than once in the same source file. It can't prevent it from being included via multiple source files. Remember that the objects from all the sources get linked into a single object, and hence the conflict.
Let's say you have another header that is also included in the source files, called foo.h, which in turn includes constants.h. The file constants.c will try to include constants.h twice (once directly via constants.h and again via foo.h). The include guard works here, and constants.h will only be included once.
Same thing will happen with foo.c. It will try to include constants.h twice (once directly via constants.h and again via foo.h). The include guard works here too, and constants.h will only be included once.
But then the two objects, constants.o and foo.o will be linked together, each with its single copy of the EXPORT via constants.h. This adds up to two.
You want to make sure that exports appear in the final link just once. One way to do that would be to take them out of a common file like constants.h, and move them to a file called exports.c.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is it possible to #Include in a “diamond heritage” stracture?
I'm building some program who looks like that:
"a.c" #includes "a.h" and #includes "b.h"
"b.c" #includes "b.h"
lets say I declare on a variable only in "b.h", named "var"
While tying to compile that on "cmd" with "nmake" I get the following error:
b.obj : error LNK2005: var already defined in a.obj
But I didn't define it on a.c or a.h, Only on b.h
What can cause this?
thanks
But I didn't define it on a.c or a.h, Only on b.h
That's not how it works. All code from all included headers is put together by the preprocessor and passed to the compiler, which then compiles it into an object file. This code is called a "translation unit." If the same variable is defined in another translation unit, it will also be present in the generated object file. When you then link these object files together, both will have the same variable defined, and thus the linker will complain about the duplicate symbol.
What you should do instead is define the variable in one *.c file, and only declare it extern in the *.h file. That way, the other translation units will know about the variable but will not try to define it themselves. It will only be defined in the translation unit that includes the *.c file where it's actually defined.
I have a header file x.h which is included by more than one *.c source files.
This header file has some structure variables defined.
I have put multiple inclusion prevention guard at the beginning of the header file as:
#ifndef X_H
#define X_H
...
..
//header file declarations and definitons.
#endif//X_H
On building I get linker errors related to multiple definitions. I understand the problem.
Won't a multiple inclusion prevention guard at the top of header file as I have, prevent multiple inclusions of the header file x.h and thereby avoid multiple definitions of the variables that are there in x.h?
#pragma once does not work on this particular compiler, so what is the solution?
Someone had posted this answer to a similar question. It doesn't seem to work for me. How does this solution work?
If the linker is complaining, it means you have definitions rather than just declarations in your header. Here's an example of things that would be wrong.
#ifndef X_H
#define X_H
int myFunc()
{
return 42; // Wrong! definition in header.
}
int myVar; // Wrong! definition in header.
#endif
You should split this into source and header file like this:
Header:
#ifndef X_H
#define X_H
extern int myFunc();
extern int myVar;
#endif
C Source:
int myFunc()
{
return 42;
}
int myVar;
Header guards are only good for a single compilation unit, i.e., source file. If you happen to include a header file multiple times, perhaps because all headers included from main.c in turn include stdio.h then guards will help.
If you have the definition of a function f in x.h which is included by main.c and util.c, then it is like copying and pasting the definition of f into main.c when creating main.o and doing the same for util.c to create util.o. Then the linker will complain and this happens despite your header guards. Having multiple #include "x.h" statements in main.c is possible of course because of these guards.
Using include guards prevents one compilation unit from including the header twice. E.g. if header B.h includes A.h and B.cpp includes A.h and B.h, everything from A.h would be declared twice in the compilation B.cpp if you weren't using include guards.
Your include guards prevent this from happening, all's fine till now.
But you get multiple definitions at link time, i.e. two compilation units define the same thing, this probably means you got a real definition in your header, use extern for all variables, make sure functions are either inline or are defined in the cpp file.
If the functions aren't large, you can use "inline" before them and the linker won't complain.
Using a multiple inclusion guard prevents compiler errors, but you're getting a linker error. Do you have data definitions in the header file that don't use extern?
Maybe X_H is already defined somewhere else? I just ran into this issue, where Xlib defines X_H in /usr/include/X11/X.h.
To check, you can call gcc -dM -E (if you are using gcc), e.g. in the buildsystem I’m using that works with CC=gcc CFLAGS="-dM -E" make. If the output file contains #define X_H even though you remove it from your file (use Y_H for example), then it is already defined outside your source code.