Reputation: 27
I have a struct defined in
a.h
#IFNDEF
#define A_H
struct a_struct
{
int val;
int val_b;
}a;
#endif
and both main.cpp and a.cpp included the header
#include "a.h"
when I use makefile with the following:
a.o: a.cpp a.h
g++ -std=c++11 -c $<
main.o: main.cpp a.h
g++ -std=c++11 -c $<
main: main.o a.o
g++ -std=c++ $^ -o $@
A compilation error occurs:
duplicate symbol '_a' in:
a.o
main.o
Is a
being redefined in a.cpp and main.cpp?
Is there a way to resolve this issue without changing a.h?
In case that's not possible, how may I change the code?
Thank you in advance :)
Upvotes: 0
Views: 123
Reputation: 180161
The problem is that a.h
both declares a data type struct a_struct
and declares a
as a variable of that type. Each translation unit that includes that header -- for example, the one based on a.cpp
and the one based on main.cpp
will therefore declare its own a
, and if two such translation units contribute to the same program then undefined behavior results. The program being rejected on account of duplicate symbols is one possible (and fairly common) manifestation of the UB arising from such circumstances.
So,
Is a being redefined in a.cpp and main.cpp?
Yes. The declaration of a
included into the translation unit of each of those source files directly causes a
to be defined in each. Technically, these declarations are not themselves the definitions, but that's a bit hair-splitting.
Is there a way to resolve this issue without changing a.h?
If the program were modified so that only one translation unit in it #include
s a.h
, whether directly or indirectly, then it would not have multiple definitions of a
(from the source it now has them). It is unclear whether that would be a viable solution for you, but that seems doubtful.
In case that's not possible, how may I change the code?
The simplest change would be to remove the declaration of a
from a.h
:
#ifndef A_H
#define A_H
struct a_struct
{
int val;
int val_b;
}; // <-- the main change is here
#endif
If you actually need an external variable a
of type struct a_struct
then you should declare it extern
in the header by adding
extern struct a_struct a;
to the header
AND
adding a non-(explicitly-)extern
declaration of a
in exactly one of the .cpp files:
struct a_struct a;
From its name, it seems like file a.cpp
would be the right place for the latter, but if you don't want to modify that then you can use main.cpp
instead.
Upvotes: 1