我有一个c代码,可以使用gcc在Linux中编译。但是当我尝试使用microsoft visual studio c ++ 2008 express edition编译它时,使用ide,它会显示错误
vec.obj : error LNK2005: _INIT_SETA already defined in a.obj
fatal error LNK1169: one or more multiply defined symbols found
我检查了头文件,所有这些文件都有预处理器防护,以防止多次包含头文件,例如。
#ifndef _vec_h_
#define _vec_h_
然后我尝试在visual studio命令提示符下编译它,
cl main.c
可以编译。问题是什么?
答案 0 :(得分:1)
“找到一个或多个乘法定义的符号”是链接器错误而不是编译器错误。当两个或多个目标文件包含同一符号的定义时,会发生这种情况。在这种情况下,vec.obj
和a.obj
都包含_INIT_SETA
符号的条目,因此您需要弄清楚vec.obj
和{{1}的来源每个符号都会在其各自的翻译单元(编辑)中引入a.obj
符号。
请注意,_INIT_SETA
是C标识符_INIT_SETA
的编译器生成的符号。也许通过宏观扩张来概述INIT_SETA
的定义?在这种情况下,INIT_SETA
的声明可能需要声明INIT_SETA
。
存在“多符号”问题不会影响源文件的编译;相反,链接步骤将失败,因为链接器不知道要链接哪个static
条目。
答案 1 :(得分:1)
您发布的错误表明存在vec.c
和a.c
(假设您没有尝试在预先存在的目标文件中进行链接),两者都定义INIT_SETA
。这是链接器错误,而不是编译错误。
cl main.c
仅将文件编译为目标文件,没有链接。如果您尝试使用命令行中的(link.exe)将所有目标文件链接在一起,则仍会出现相同的错误。搜索错误中列出的两个文件,以获取INIT_SETA
符号的多个定义。
一种可能的解决方案是使用它在两个文件中的一个文件中声明extern
,然后这两个文件将共享同一个实例。
如果两个文件都需要私有副本,则应取出头文件中出现的任何extern INIT_SETA
声明(并将static
添加到每个源文件中的定义中)。
答案 2 :(得分:0)
I checked the header files, and all of them have the preprocessor guard to prevent the header to be included multiple times
这只能防止预处理器在单个编译单元(cpp文件)中多次包含单个头文件。因此,您仍然在两个cpp文件中都包含该标头,并且该标头定义了一个_INIT_SETA对象。如果标头仅包含声明而不包含定义,则可以避免此问题。 (没有函数代码,也没有全局变量。)
Hpp文件:
#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文件:
#include "vec.h"
vector::function() {} //function definition only in this cpp file
vector myvector; //variable instantiation only in this cpp file
唯一的例外通常是模板,它完全在头文件中,链接器自己计算出来。