C duplicate symbol error

I have added some const character in my file as under. The error i get is duplicate symbol _xyz(say). What is the problem with it and how could i get out of this. const char* xyz = "xyz"; class A...

I have added some const character in my file as under. The error i get is duplicate symbol _xyz(say). What is the problem with it and how could i get out of this.

const char* xyz = "xyz";
class Abc
{
public:
    Abc()
    {
    }
};

paxdiablo's user avatar

paxdiablo

838k230 gold badges1561 silver badges1929 bronze badges

asked May 24, 2010 at 5:38

boom's user avatar

If this is in a header file, you’re defining xyz every time you #include it.

You can change the declaration as @R Samuel Klatchko shows. The usual way (if the data isn’t const) is like this:

In Abc.h:

extern char *xyz;

In Abc.cpp:

char *xyz = "xyz";

Edited to add

Note that header guards will not solve this problem:

#ifndef XYZ_H
#define XYZ_H
...
#endif

Header guards prevent «redefinition» errors, where the same symbol appears twice in the same compilation unit. That’s a compiler error.

But even with header guards the definition of xyz will still appear in every source file that includes it, causing a «duplicate symbol» error, which is a linker error.

It would have been more helpful if the original poster had mentioned that, of course.

answered May 24, 2010 at 5:39

egrunin's user avatar

egruninegrunin

24.5k8 gold badges49 silver badges92 bronze badges

2

The problem is every source file that includes your header file gets it’s own copy of xyz with external linkage.

The easiest way to fix that is to give xyz internal linkage. You can do that by making the pointer itself const in addition to having the underlying char’s const:

const char* const xyz = "xyz";

answered May 24, 2010 at 5:41

R Samuel Klatchko's user avatar

R Samuel KlatchkoR Samuel Klatchko

74k15 gold badges133 silver badges186 bronze badges

1

I also ran into this issue, but for me the solution was different. I had put overloaded operators (==, !=, <<) in my header file and implemented them. This was causing an issue in other files where I also used ==, !=, or <<. To solve this, I moved the implementation into the .cpp file and left the declaration in the header file.

Edit:

This can also be caused if:

  • You are including .cpp files instead of .h files. You can fix this by switching the import to use .h instead of .cpp.
  • You are implementing static functions inside a header file (outside of the class declaration). You can fix this by moving the implementations into a .cpp file (among other solutions).

answered Jan 22, 2019 at 20:19

Eric Wiener's user avatar

Eric WienerEric Wiener

4,3192 gold badges29 silver badges37 bronze badges

1

My use-case:

  • I had multiple header files a.hpp, b.hpp, and, c.hpp which contained some utility methods.
  • I had a file util.hpp which acted as an aggregator for the above files.

In my case, the extern did not work but static worked.

I had to use:

  • header guards to avoid errors in Visual Studio code.
  • static with functions to avoid compile-time errors.

Check out this article too.

answered Jan 5, 2022 at 2:17

DeltaCap019's user avatar

DeltaCap019DeltaCap019

6,5342 gold badges47 silver badges69 bronze badges

Ever run into this one?

duplicate symbol _name in:
/var/folders/6x/vqbtyyvd5r136lb7hpb0qvmw0000gp/T/1-siEqxi.o
/var/folders/6x/vqbtyyvd5r136lb7hpb0qvmw0000gp/T/2-bMFgvM.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [all] Error 1

It’s a bitch. Lemme explain what’s up.


A contrived example

Let’s say you have the following files:

#include "name.h"

int main(int argc, char* argv[]) {
    say_name();
    return 0;
}
#ifndef NAME_H
#define NAME_H

char* name = "Heisenberg";
void say_name();

#endif
#include <stdio.h>
#include "name.h"

void say_name() {
    printf("%sn", name);
}
all:
    cc main.c name.c -o say_my_name

When you run make, you get the error we spoke about in the intro to this
article. Yours may differ slightly if you’re not using clang and not on a Mac,
but the premise will be the same: it thinks you’re defining the variable name
twice.


Isn’t this what the include guard is meant to prevent?

Not quite… It’s tempting to think that if we wrap an ifndef preprocessor
directive around our headers they’ll only be included once in our program, but
that idea stems from a misunderstanding of what headers are for and how our
programs go from C into machine code.

Let’s dive into what the cc command is doing.


Compiler drivers

The compilation of your code is a multi-stage thing that invokes a number of
different tools. The cc command just wraps them all up nicely for us so that
we don’t have to worry about them. This is called a «compiler driver», because
it drives the full compilation process for us.

Here’s what’s going to happen when we run make:

  • Run the C preprocessor, cpp on main.c
  • Compile the preprocessed main.c into assembly code, main.s
  • Assemble main.s into machine code in an «object file», main.o
  • Repeat the above three steps for name.c to get name.o
  • Link main.o and name.o together to create the executable name

To illustrate:

main.c -> main.s -> main.o
                           
                            *> - say_my_name
                           /
name.c -> name.s -> name.o


What the hell is an object file?

An object file consists of, at least, a symbol table and some machine code. It’s
a binary file that contains all of the functions and data from a specific C file
in a way that allows other programs to pick and choose things to use from it.


What the hell is a symbol table?

A symbol table is a set of key/value pairs. When you write a function, the
function name is the key for that function’s value, which is its binary code.
Similarly, when you define variables, the name of the variable is the key and
the value is, well, the value.

Let’s take a look at an object file’s symbol table:

$ nm name.o
0000000000000060 s EH_frame0
0000000000000026 s L_.str
0000000000000031 s L_.str1
0000000000000038 D _name
                 U _printf
0000000000000000 T _say_name
0000000000000078 S _say_name.eh

The nm command allows us to see what symbols are in an object file. Symbols
come in a variety of shapes and sizes. In the output above, we have the address
of the symbol, the type of the symbol and the name of the symbol.

If you take a look inside the object file, you’ll notice that the addresses
specified above aren’t references to how many bytes into the file the symbol is.
Object files have «headers», which describe how to read the file and what
«sections» it contains.

Object files have a number of different «sections». They’re just logical
separations. The «text» section is code, the «data» section is initialized data
(any globally initialised constant ends up in here), and the «BSS» section is
for uninitialised data. There are some more sections but these are the ones
important to our explanation.

The symbol type «T» refers to code, the symbol type «D» refers to data. Notice
our _say_name and _name symbols. Also notice _printf, which is type «U»,
which means «undefined». This is because we’ve used the printf function but
haven’t defined it. It’s defined in libc, which comes in at a later stage in
the compilation process.

How about we take a look inside main.o as well?

$ nm name.o
0000000000000060 s EH_frame0
0000000000000026 s L_.str
0000000000000031 s L_.str1
0000000000000038 D _name
                 U _printf
0000000000000000 T _say_name
0000000000000078 S _say_name.eh

Hrm. This object file also has a _name symbol. If we use the strings
command, the situation starts to make sense:

$ strings main.o
Heisenberg
$ strings name.o
Heisenberg


Aha!

Both files contain the symbol and the string constant! Because the compilation
process does each C file separately and then links them together later, both
object files end up having their own definition of _name, which causes the
linker to throw the duplicate symbol error.


The solution!

If you just scrolled to here from the error message at the top of the post,
that’s cool but I recommend giving the post a read so that this solution makes
sense.

You need to move the declaration of name out of the header file and into the
C file.

Doing this doesn’t change the object file for name.o in the slightest. The
_name symbol will still be in there and you don’t need to make any changes to
main.c. You just avoid accidentally redefining name in main.c through the
inclusion of name.h.

The changed files:

#ifndef NAME_H
#define NAME_H

void say_name();

#endif
#include <stdio.h>
#include "name.h"

char* name = "Heisenberg";

void say_name() {
    printf("%sn", name);
}
$ make
cc main.c name.c -o say_my_name
$ ./say_my_name
Heisenberg

And we’re golden :)


Q: What if I want to access the name variable in main.c?

The _name symbol is accessible inside name.o, you just have to tell main.c
to look for it.

If we take a look at the new symbol table for main.c, we’ll see no reference
to _name:

$ nm main.o
0000000000000048 s EH_frame0
0000000000000000 T _main
0000000000000060 S _main.eh
                 U _say_name

This is what the extern keyword is for in C. Check this out:

#include <stdio.h>
#include "name.h"

extern char* name;

int main(int argc, char* argv[]) {
    printf("%sn", name);
    return 0;
}

Build and run:

$ make
cc main.c name.c -o say_my_name
$ ./say_my_name
Heisenberg

The error: duplicate symbol for architecture x86_64 will be prompted
if the following files are compiled.

  • makefile
  • main.cpp
  • utils.h
  • hello.h
  • hello.cpp
  • bye.h
  • bye.cpp

You will see the duplicate symbol for architecture x86_64 error
when you compile those files.

make
g++ -c -Wall bye.cpp
g++ -c -Wall hello.cpp
g++ -Wall main.cpp bye.o hello.o -o run
duplicate symbol __Z3LOGNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE in:
    bye.o
    hello.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [all] Error 1

The reason is that we include the shared header(utils.h)
into different files(bye.cpp and hello.cpp),
and compile those files into different libraries(bye.o and hello.o),
so the functions in the shared header(LOG)
duplicate in those different libraries.

Thus, when we try using those different libraries(bye.o and hello.o)
at the same time, there are duplicated symbols for functions(LOG)
included from the shared header(utils.h).
The program has no idea about which one it should call
among those duplicated symbols.

Approach 1: Using macros instead of functions

The macro is only textual substitution that expanded by the preprocessor,
so there is no symbol generated.

You can replace function LOG by

#define LOG(s) (std::cout << s << std::endl)

Then the SayBye() will be expanded into:

void SayBye()
{
  (std::cout << "Goodbye" << std::endl);
}

You can run: $ g++ -E <file_name>.cpp to watch
and confirm the preprocessor’s output.

Approach 2: Make functions inline

It works almost same as macro.
Inline functions are actual functions
whose copy of the function body are injected directly into
each place the function is called.

inline void LOG(std::string s)
{
  std::cout << s << std::endl;
}

The insertion occurs only if
the compiler’s cost/benefit analysis shows it to be profitable.
Same as the macros, inline expansion eliminates
the overhead associated with function calls.

Inline functions are parsed by the compiler,
whereas macros are expanded by the preprocessor.
The preprocessor macros are just substitution patterns in code
before the compilation,
so there is no type-checking at that time.
While inline functions are actual functions, so compiler can keep an eye on
type-checking issues to help debugging.

See here for more details.

Approach 3: Using static to make functions local in each file

Since their states are not sharable,
they should not visible across each other.
Thus, the generated symbols are also local in each file.

static void LOG(std::string s)
{
  std::cout << s << std::endl;
}

TL;DR: You are including it twice. Solution at the end of the comment.

It will be useful to understand the basic flow of a C++ program during development.

Code -> Preprocessor -> Compiler -> Object files -> Linker -> Executable

The thing to note is that compiling does not directly result in an executable file. Also, compilation can generate multiple object files each containing their own symbols.

The linker then, in a sense, combines the object files into the executable. Part of its job is to make sure there are no conflicts. Since many libraries and object files can be linked against to create an executable, it’s possible to have functions with identical signatures but different implementations; there would be no way to know which one to call. Therefore the linker errors when it finds identical signatures even if it happens to be caused by the same code.

So what’s happening is some code which uses the XML parsing library, specifically this «CSPXMLParser::UTF8String::to<string>(string&) const» function, is getting compiled into dStructFill.o. Separately, the same function is getting compiled into main.o. Thus, dStructFill.o and main.o each have a symbol which, while fine individually (hence no compile error), conflicts with the symbol in the other file. (And, actually, all the functions conflict. The one in the error is just the first one the linker got to.)

Basically, main and StructFill are different compilation units, leading to different object files, and each include the header file, resulting in the error. The error goes away when you combine all the files because there aren’t multiple inclusions and only one object file is created, meaning one definition of everything, leaving no room for such linking errors.

The solution is to make sure the function is only defined in one place. Sometimes you have to do this with the extern keyword (indicating the specific function/variable/whatever is already defined elsewhere) but, for you, it’s simply that the information in your header file is being included twice because you didn’t guarantee it only happens once. This is an easy fix. Wrap your header file in a #ifndef statement, like this:

#ifndef CLASS_H
#define CLASS_H
...
#endif

This can be read as: if the class is not defined, define it, otherwise don’t worry about it because, well, it’s already defined. Wrapping headers in #ifndef statements like this is good practice in general as it ensures no conflicts and helps prevent unexpected behavior. It works by using the preprocessor, which effectively modifies the source code before it gets parsed by the compiler, yielding a complete definition when compiling one object file and becoming whitespace when compiling the other.

EDIT: Rereading your question, I think you already understood the development flow and how the linker works, sorry if I went in to all that unnecessarily; hopefully something in there was still useful to you :).

  • Forum
  • Beginners
  • Duplicate symbol error

Duplicate symbol error

I am new to c++ and programming in general. Thus, please excuse me if this question seems trivial but I would appreciate anyone’s help.

I am learning object oriented programming and I decided to create a date program separated in 3 files. However, when I run my program I get the following error:

ld: 17 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Testing] Error 1

My question is: how can I fix this duplicate symbol error? here is my code. I tried to comment it out as much as possible to make it easier for whoever might want read it

header file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 #ifndef CHRONO_H_
#define CHRONO_H_
#include<sstream>

using namespace std;
namespace Chrono { // name space for class and helper functions
enum  class Month { //enum for the months of date class
	jan = 1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec
};
class Date {
	 int day, year;
	 Month month;
public:
	Date();
	Date(Month m, int d, int y);
	int getDay() const;
	Month getMonth() const;
	int getYear() const;
	void addDay (int d);
	void addMonth(Month m);
	void addYear(int n);
};
bool leapYear(int y); // to identify a leap year
bool isDate(Month m, int d, int y); // returns true if the date has the right month and right days of month
Month& operator ++(Month& m); // to add one to enum and get to next month
bool operator ==(Date& a, Date& b);
bool operator != (Date& a, Date& b);
ostream& operator <<(ostream& os, Date& d);
istream& operator >>(istream& is, Date& dd);
}
#endif /* CHRONO_H_ */ 

definitions.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  #include <iostream>
#include "Chrono.h"

using namespace std;
//definitions
namespace Chrono {
int Date:: getDay() const {return day;}
Month Date::getMonth() const {return month;}
int Date::getYear() const {return year;}
bool leapYear(int y) {
	if (y % 4 == 0) return true;
	return false;
}
bool isDate(Month m, int d, int y) {
	if(d <= 0) return false;
	if (m < Month::jan || m > Month::dec) return false;
	int daysInMonth = 0;
		switch (m) {
		case Month::feb:
			if (leapYear(y)) {
				daysInMonth = 29;
			} else {
				daysInMonth = 28;
			}
			break;
		case Month::apr: case Month::jun: case Month::sep: case Month::nov:
			daysInMonth = 30;
			break;
		case Month::jan: case Month::mar: case Month::may: case Month::jul: case Month::aug: case Month::oct: case Month::dec:
			daysInMonth = 31;
		}

	if (d  > daysInMonth) return false;

	return true;
}
Month& operator ++(Month& m) { // to add one to month and make sure it comes back to jan after dec
	m = (m == Month::dec) ? Month::jan: Month(int(m) + 1);
	return m;
}
bool operator ==(Date& a, Date& b) {
	return a.getDay() == b.getDay()
			&& a.getMonth() == b.getMonth()
			&& a.getYear() == b.getYear();
}
bool operator != (Date& a, Date& b) {
	return a.getDay() != b.getDay()
			&& a.getMonth() != b.getMonth()
			&& a.getYear() != b.getYear();
}
ostream& operator <<(ostream& os, Date& d) {
	os <<int (d.getMonth()) <<"/"
		<<d.getDay() <<"/"
		<<d.getYear();
	return os;
}
istream& operator >>(istream& is, Date& dd) {
	int d, m, y;
	char c1, c2;
	is >> m >> c1 >> d >> c2 >> y;
	if (c1 != '/' || c2 != '/') {
		is.clear(ios::failbit); // If wrong format, set the fail bit
		return is;
	}
	dd = Date (Month (m), d, y);
	return is;
}
Date::Date(): day(1), year(2001), month(Month::jan) {} // default constructor
Date::Date(Month m, int d, int y) {
	if (isDate(m, d, y)) {
		month = m;
		day = d;
		year = y;
	}else {
		cerr<<"This is not a valid date";
	}
}
void Date::addDay(int d) { //add day to date  but check if it woulc create a valid date first
	if (isDate(month, d, year)) d++;
}
void Date::addMonth(Month m) {// go to next month with overloaded ++ but check month first
	if (m < Month::jan || m > Month::dec) {
		cerr<<"This is not a valid month"<<endl;
	} else {
		++m;
	}
}
void Date::addYear(int n) {
	// check if current year is leap year before adding 1. If so, date is changed to mar 1, year+1
	if (month == Month::feb && day == 29 && !leapYear(year + n)) {
		month = Month::mar;
		day = 1;
	}
	year += n;
}
}

my main:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include "Chrono.h"
#include "Chrono.cpp"

using namespace std;
using namespace Chrono;

int main () {
	Date d1;
	cout<<d1;

return 0;
}

originally I had my getter function for the date class defined inside the class declaration and the run time error would say 14 duplicates instead of 17. I assume that it has to do with my data members and parameter values being duplicated each time I #include Chrono.h. I found a post online saying that creating a static data member and member function might help but I am not entirely sure how that would work.

Thank you for reading through my post and I apologize for it being so lenghty.

Last edited on

Hi,

Just a stab in the dark:

Don’t include cpp files, just the header file is sufficient.

Try and get rid of using namespace std; that is an easy way to generate conflicts. Put std:: before each std thing.

With the days in a month thing, it’s easier to look up an array of month values with a subscript of the month number.

For Leap Years, there is more to it than that: every 4 years is, every 100 is not, every 400 is.

(year % 4 == 0 && year % 100 != 0) || year % 400 == 0;

Last edited on

wow! I can’t believe it was so simple. Thanks a a lot for your advice! I know it can be a somewhat tedious to go through someone’s code so I appreciate it.

Topic archived. No new replies allowed.

Я собираю 2 файла C ++ вместе. 4, если вы включите заголовочные файлы. Проблема в том, что я продолжаю получать ошибки «Duplicate Symbol», когда компоновщик пытается связать файлы вместе.

Вот мои файлы.


main.h

int test2();

main.cc

#include "main.h"#include "test.h"
int test2(int test) {
return 0;
}

int main() {

test2(test());
return 0;
}

test.h

int hello = 10;
int test();

test.cc

#include <iostream>
#include "test.h"using namespace std;

int test() {
cout << hello << endl;
return 0;
}

Я думаю, что делаю что-то простое неправильно. Может кто-нибудь указать, что я делаю не так.
Вот как я собираю файлы.

c++ main.cc test.cc -o main

Вот ошибка, которую я получаю:

duplicate symbol _hello in:
/var/folders/nj/568_95bj4dg9v11l_mksv_2m0000gn/T/main-3becdd.o
/var/folders/nj/568_95bj4dg9v11l_mksv_2m0000gn/T/test-e84473.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

0

Решение

В заголовочном файле объявите переменную:

extern int hello;

В одном исходном файле определите переменную:

int hello = 10;

Не определяйте переменные в заголовках — это эквивалентно определению их в каждом исходном файле, который включает заголовок, и именно это вызывает ошибку компоновщика.

9

Другие решения

Вы можете просто определить привет как «статическую» (глобальную) переменную

static int hello = 10;

Более подробная информация упоминается в аналогичном вопросе:

Повторяющиеся символы при связывании

0

Hello, I downloaded xcode 12 to learn the C language at school but each time I run my code the message «Build failed» is displayed then there is an error «1 duplicate symbol for architecture x86_64» Can you help me please

Replies

For anyone to help you, you need to provide more information. List the steps you take to create the Xcode project. What kind of Xcode project did you make? If you create a command-line tool project and run it, do you get the Duplicate Symbol error message?

List anything else you do before building the project, such as any files you added to the project. A common cause of a Duplicate Symbol error message in a C project is to create a command-line tool project, add a new file, and add a main function to the new file. The project comes with its own main function so you end up with two main functions. A C program can have only one main function.

When creating the xcode project I chose the command line tool and choose c file after creating it there is a first file that displays hello word but each time I create a new c file there is another one with the extension.h which I do not understand but in codand in the c file when I run it the error is displayed

The .h file is a header file. Most C files have an accompanying header file.

If you create a command-line tool project and run it without adding any files, do you get the Duplicate Symbol error message?

Show the code in the new C files you’re creating. When I create a command-line C project, add a C file with a header, and run the project, the project builds and prints Hello, world to the console.

When i create the command-line tool project and run it without adding file i don’t get the duplicate message
the code :

#include <stdio.h>
int main ()

{

  int (a);
  int (b);
  int (i);
  printf(«Give a number»);
  scanf(«%d»,&a);
  for (i=1;i<=10;i++)
  {

    b=a*i;
    printf(«%d*%d=%dn»,a,i,b);
  }
}

Are you adding a new file to the project and adding that code? If so, you have two main functions, giving you a Duplicate Symbol error. A C program can’t have two main functions. Remove the main function in the main.c file that was created when you created the project.

When you create a command-line tool project, Xcode provides a main.c file. Why are you creating another file instead of using the main function Xcode created for you.

Ah ok now I understand because that’s what I used to do
by removing the main function it worked thanks for your help🙏🏽

Means that you have loaded same functions twice.

Понравилась статья? Поделить с друзьями:
  • C cin int error
  • C builder socket error
  • C builder error detected lme200
  • C 4521 ошибка коника
  • C 32 11 ошибка камера сони