1
votes

I have a c codes which can be compiled in Linux using gcc. But when I try to compile it using microsoft visual studio c++ 2008 express edition, using the ide, it shows the error

vec.obj : error LNK2005: _INIT_SETA already defined in a.obj
fatal error LNK1169: one or more multiply defined symbols found

I checked the header files, and all of them have the preprocessor guard to prevent the header to be included multiple times, e.g.

#ifndef _vec_h_
#define _vec_h_

Then I tried compiling it in visual studio command prompt,

cl main.c

It can be compiled. What is the problem?

3
Have you tried cleaning the solution/project and rebuilding it? Visual Studio could be compiling files in a different order each time (or you change just one file that needs recompiling), so you may have older obj files with the definitions already present?Nick Shaw
Thanks Nick! It really helps! I exclude all files and only have main.c in the project, and now it can compile.Thank you Pratorian and Daniel, I guess it is really the linking problem, but somehow having the main.c alone solves the problemMichael

3 Answers

2
votes

The error you posted indicates the existence of a vec.c and a.c (assuming you're not trying to link in pre-existing object files), both of which define INIT_SETA. This is a linker error, not a compilation error.

cl main.c only compiles the file to an object file, there is no linking going on. If you try to link all your object files together using (link.exe) from the command line, you'll still get the same error. Search the two files listed in the error for multiple definitions of the INIT_SETA symbol.

One possible solution could be to declare it extern in one of the two files using it, then the two files would share the same instance.

If both files need to have private copies, you should take out any extern INIT_SETA declarations appearing in the header files (and add static to the definitions in each source file).

2
votes

"one or more multiply defined symbols found" is a linker error rather than a compiler error. It occurs when two or more object files contain a definition for the same symbol. In this case, both vec.obj and a.obj somehow both contain an entry for the _INIT_SETA symbol, so you need to figure out how the sources for vec.obj and a.obj each introduce an _INIT_SETA symbol into their respective translation units (compilations).

Note that _INIT_SETA is the compiler-generated symbol for the C identifier INIT_SETA. Perhaps a definition of INIT_SETA was inlined via macro expansion? In this case, the declaration of INIT_SETA likely needs to be declared static.

The presence of a "multiple symbol" issue does not affect compilation of the source files; rather the linking step will fail because the linker does not know which _INIT_SETA entry to link with.

2
votes

I checked the header files, and all of them have the preprocessor guard to prevent the header to be included multiple times
This only prevents the preprocessor from including a single header file multiple times in a single compilation unit (cpp file). So you still have that header included in both cpp files, and that header defines a _INIT_SETA object. The problem is avoided if headers contain only declarations, and not definitions. (No function-code, and no global variables.)

Hpp file:

#ifndef _vec_h_
#define _vec_h_
class vector {
    function();  //function prototype.  No definition
};  //class declaration.  No instantiation
extern vector myvector;   //variable declaration.  No instantiation
#endif //_vec_h_

Cpp file:

#include "vec.h"

vector::function() {} //function definition only in this cpp file

vector myvector; //variable instantiation only in this cpp file

The only exceptions are usually templates, which goes entirely in the header file, and the linker figures it out itself.