"Multiple definition", "first defined here" errors

255.8k Views Asked by At

I have 3 projects: Server, Client and Commons. Making header & source pairs in Commons doesn't cause any problems and I can access the functions freely from both Server and Client.

However, for some reason making additional source/header files within Server or Client project always causes multiple definition of (...) and first defined here errors.

Example:

commands.h (in root dir of the Client project)

#ifndef COMMANDS_H_
#define COMMANDS_H_

#include "commands.c"

void f123();

#endif /* COMMANDS_H_ */

commands.c (in root dir of the Client project)

void f123(){

}

main.c (in root dir of the Client project)

#include "commands.h"
int main(int argc, char** argv){

}

Errors:

make: *** [Client] Error 1      Client
first defined here              Client
multiple definition of `f123'   commands.c

Cleaning, rebuilding index, rebuilding projects doesn't help. Neither does restarting the computer.

6

There are 6 best solutions below

2
On BEST ANSWER

The problem here is that you are including commands.c in commands.h before the function prototype. Therefore, the C pre-processor inserts the content of commands.c into commands.h before the function prototype. commands.c contains the function definition. As a result, the function definition ends up before than the function declaration causing the error.

The content of commands.h after the pre-processor phase looks like this:

#ifndef COMMANDS_H_
#define COMMANDS_H_

// function definition
void f123(){

}

// function declaration
void f123();

#endif /* COMMANDS_H_ */

This is an error because you can't declare a function after its definition in C. If you swapped #include "commands.c" and the function declaration the error shouldn't happen because, now, the function prototype comes before the function declaration.

However, including a .c file is a bad practice and should be avoided. A better solution for this problem would be to include commands.h in commands.c and link the compiled version of command to the main file. For example:

commands.h

#ifndef COMMANDS_H_
#define COMMANDS_H_

void f123(); // function declaration

#endif

commands.c

#include "commands.h"

void f123(){} // function definition
0
On

You should not include commands.c in your header file. In general, you should not include .c files. Rather, commands.c should include commands.h. As defined here, the C preprocessor is inserting the contents of commands.c into commands.h where the include is. You end up with two definitions of f123 in commands.h.

commands.h

#ifndef COMMANDS_H_
#define COMMANDS_H_

void f123();

#endif

commands.c

#include "commands.h"

void f123()
{
    /* code */
}
2
On

This error can also occur if the definitions are "header file only". Example :

foo.h :
#ifndef FOO
#define FOO
int myFunc(int a) {
 return a+2;
}

#endif

// There is no foo.c

// Main source files
file1.c :
#include "Foo.h"
<some code>

file2.c :
#include "Foo.h"
<some code>

Now both file1.c and file2.c contains definition of myFunc(). This will cause linker error when they are getting linked to same library.

0
On

Maybe you included the .c file in makefile multiple times.

5
On

I had a similar issue when not using inline for my global function that was included in two places.

0
On

I am adding this A because I got caught with a bizarre version of this which really had me scratching my head for about a hour until I spotted the root cause. My load was failing because of multiple repeats of this format

<path>/linit.o:(.rodata1.libs+0x50): multiple definition of `lua_lib_BASE'
<path>/linit.o:(.rodata1.libs+0x50): first defined here

I turned out to be a bug in my Makefile magic where I had a list of C files and using vpath etc., so the compiles would pick them up from the correct directory in hierarchy. However one C file was repeated in the list, at the end of one line and the start of the next so the gcc load generated by the make had the .o file twice on the command line. Durrrrh. The multiple definitions were from multiple occurances of the same file. The linker ignored duplicates apart from static initialisers!