Hatefiend Hatefiend - 3 months ago 13
C Question

Linker error for multiply defined symbols

I have the following file structure:

X.h

#pragma once

#include "Y.h"

int ONE = 1;

int combine();


X.c

#include "X.h"

int combine()
{
return ONE + TWO;
}


Y.h

#pragma once

int TWO = 2;


Y.c

#include "Y.h"


Main.c

#include "X.h"

int main()
{
int fusion = combine();

return 0;
}


I get the following errors:

LNK1169 one or more multiply defined symbols found

LNK2005 _ONE already defined in Main.obj

LNK2005 _TWO already defined in Main.obj

KLNK2005 _TWO already defined in Main.obj


This makes zero sense. If we start at
Main.c
the compiler must include
X.h
. The compiler then looks for the C file associated with
X.h
. Inside
X.c
it needs to include
X.h
but
#pragma once
SHOULD guard against that. Then it needs to include
Y.h
. It looks for the C file and finds
Y.c
which says to include
Y.h
, but
Y.h
has already been included. Then, it returns to Main.c and should successfully compile... but nope.

I can add
/FORCE
to my project settings which makes my code run perfectly but still outputs the:

ONE has already been defined, second definition ignored.

Answer

but #pragma once SHOULD guard against that

#pragma once is used to avoid reduplicate including within single translation unit (.c file in this case), but it can't prevent multiple definition crossing multiple translation unit.

You're defining global variable ONE and TWO in .h file, and they're included in multiple translation unit and cause multiple definition error.

For example, finally, ONE will be defined in X.c and Main.c, TWO will be defined in Y.c, X.c and Main.c.

You should declare ONE and TWO in .h file (by using extern), and define them in .c file.

X.h

#pragma once

#include "Y.h"

extern int ONE;
int combine();

X.c

#include "X.h"

int ONE = 1;

int combine()
{
    return ONE + TWO;
}

Y.h

#pragma once

extern int TWO;

Y.c

#include "Y.h"

int TWO = 2;