Duplicate symbol in C using Clang

isf picture isf · Jun 8, 2012 · Viewed 14.6k times · Source

I am currently working on my first "serious" C project, a 16-bit vm. When I split up the files form one big source file into multiple source files, the linker (whether invoked through clang, gcc, cc, or ld) spits out a the error:

ld: duplicate symbol _registers in register.o and main.o for inferred 
    architecture x86_64

There is no declaration of registers anywhere in the main file. It is a uint16_t array if that helps. I am on Mac OS 10.7.3 using the built in compilers (not GNU gcc). Any help?

Answer

paxdiablo picture paxdiablo · Aug 13, 2013

It sounds like you've defined a variable in a header then included that in two different source files.

First you have to understand the distinction between declaring something (declaring that it exists somewhere) and defining it (actually creating it). Let's say you have the following files:

header.h:
    void printIt(void);           // a declaration.
    int xyzzy;                    // a definition.

main.c:
    #include "header.h"
    int main (void) {
        xyzzy = 42;
        printIt();
        return 0;
    }

other.c:
    #include <stdio.h>
    #include "header.h"
    void printIt (void) {         // a definition.
        printf ("%d\n", xyzzy);
    }

When you compile the C programs, each of the resultant object files will get a variable called xyzzy since you effectively defined it in both by including the header. That means when the linker tries to combine the two objects, it runs into a problem with multiple definitions.

The solution is to declare things in header files and define them in C files, such as with:

header.h:
    void printIt(void);           // a declaration.
    extern int xyzzy;             // a declaration.

main.c:
    #include "header.h"
    int xyzzy;                    // a definition.
    int main (void) {
        xyzzy = 42;
        printIt();
        return 0;
    }

other.c:
    #include <stdio.h>
    #include "header.h"
    void printIt (void) {         // a definition.
        printf ("%d\n", xyzzy);
    }

That way, other.c knows that xyzzy exists, but only main.c creates it.