Alex Reynolds
Alex Reynolds

Reputation: 96984

Linking issue with "multiple definition of" compilation error

I have the following "constants" header:

/* constants.h */

#ifdef __cplusplus 
extern "C" {
#endif

#pragma once

#ifndef CONSTANTS_H
#define CONSTANTS_H

const char * kFoo = "foo";
const char * kBar = "bar";

#endif

#ifdef __cplusplus
}
#endif

I am #include-ing this header in files X.c and Y.c.

Note that I am not including this in X.h or Y.h.

The files X.c and Y.c get compiled into object files which are archived into a static library called libXY.a.

When I include X.h and Y.h in Z.h, and when I link to libXY.a, I cannot compile Z.c without errors:

/* Z.h */

#include "X.h"
#include "Y.h"

I get the following compilation errors when trying to compile Z.c:

/path/to/libXY.a(X.o):(.data+0x0): multiple definition of `kFoo`
/path/to/libXY.a(Y.o):(.data+0x0): first defined here
/path/to/libXY.a(X.o):(.data+0x8): multiple definition of `kBar`
/path/to/libXY.a(Y.o):(.data+0x8): first defined here

I have tried setting kFoo and kBar to extern, but that does not help.

How would I resolve multiple definitions, when I am only including the constants once (via the header guard #ifndef CONSTANTS_H)?

Upvotes: 6

Views: 8243

Answers (2)

justin
justin

Reputation: 104708

How would I resolve multiple definitions, when I am only including the constants once (via the header guard #ifndef CONSTANTS_H)?

With this in constants.h:

const char * kFoo = "foo";

a definition for kFoo will be emitted in every translation that #includes constants.h. Thus, multiple definitions, which then result in link errors.

As asaelr noted (+1), you would solve it like this:

constants.h

extern const char* const kFoo;

constants.c

const char* const kFoo = "foo";

(note that i also made the pointer const, which is usually what you want to do in this case)

Upvotes: 9

asaelr
asaelr

Reputation: 5456

You should not define variables in header file. define them in one of the source files, and declare them (extern) in the header file.

(You wrote "I have tried setting kFoo and kBar to extern, but that does not help." I guess that you didn't define them in a source file)

Upvotes: 4

Related Questions