C ++ 03链接器“已经定义的符号”没有出现在中间文件上 [英] C++03 linker "already defined symbol" doesn't appear on intermediate file

查看:66
本文介绍了C ++ 03链接器“已经定义的符号”没有出现在中间文件上的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Visual Studio 2005上的一个大型项目遇到了问题,我在那儿用光了所有的想法。

I am having a problem with a large project on visual studio 2005 on which I have run out of ideas.

我什至不能放一个工作代码段因为我不知道有什么关系,但是我会尝试:

I can't even put a working code snippet because I don't know what's related, but I will try:

我需要使项目中的每个.cpp文件都有其自己的ID号,并创建一个实例知道该ID的对象(可全局访问)的标识符。
我遵循了该线程上可接受的答案的帮助如何在c ++中管理文件唯一ID
,并使其在沙盒环境中正常工作。

I needed to make each .cpp file in my project have its own ID number, and create an instance of an object (which is globally accessible) that knows that ID. I followed the help on the accepted answer on this thread How to manage file unique IDs in c++ and made it work in a sandbox environment.

添加文件,使文件具有唯一的 #define FILEID(FileId :: ID_FileName)
,然后在沙箱上访问其实例即可正常工作。

Adding files, giving them a unique #define FILEID (FileId::ID_FileName) and then accessing their instance works fine on the sandbox.

现在来了麻烦-
我将使文件知道其IDS的代码粘贴到主项目中,并进行了编译。

Now comes the trouble - I pasted the code that makes files know their IDS to the main project, and compiled.

到目前为止一切都很好。

So far so good.

现在,我在项目中添加了一个现有的.cpp文件:

Now, I added to one of the existing .cpp files in the project:

#include "ids.h"
#define FILEID File1   // The FileId corresponding to this file
#include "global.h"

仍然可以编译,链接,一切都很好。

Still compiles, links, all good.

将这些行添加到第二个.cpp文件中项目
现在给出链接错误:

Adding these lines to a (any) second .cpp file in the project now gives link error:

其中:


  • name1:我向(alphabeticcaly)添加行的第一个文件

  • name2:其他不相关的文件名(这也可以是我向其添加行的第二个文件,但也可能只是其他文件)

错误在name2.obj中的
中:错误LNK2005:公共静态类实例& __cdecl Manager< 3> :: getInstance(void)(?getInstance @ $ Manager @ $ 02 @@ SAAAVInstance @@ XZ)已在name1.obj

The error in name2.obj : error LNK2005: "public static class Instance & __cdecl Manager<3>::getInstance(void)" (?getInstance@$Manager@$02@@SAAAVInstance@@XZ) already defined in name1.obj

有时错误仅出现在第二个文件中,有时(在连续的生成之间,没有更改)错误出现在文件夹中的每个.cpp文件上。

Some times the error is only in the second file, and sometimes (between consecutive builds without changes) the error appears on every .cpp file in the folder.

在我向其中添加了行的文件中查看中间文件(预处理器输出)显示的正是

Looking in the intermediate file (the preprocessor output) on the files to which I added the lines shows exactly one appearance of the

template <>
Instance &Manager<FILEID>::getInstance()
{
    static Instance theInstance = getTheFactory().getInstance(FILEID);
    return theInstance;
};

具有正确的FileId :: ID_FileName,该名称与
仍然,链接器认为在多个文件中使用了相同的FileId。

with the correct FileId::ID_FileName, which is a different name than that of the other file. Still, the linker thinks the same FileId is used in more than one file.

在不相关的文件上(它们也给出了确切的相同的错误),没有出现 getIns tance()。显然,链接器没有理由在那儿大喊大叫。

On unrelated files (which also give the exact same error), there is no appearance of getInstance() at all. Apparently, there shouldn't be a reason for the linker to shout there.

我检查了一下,在项目中的任何地方都没有.cpp文件。

I checked, and no .cpp files include each other somewhere in the project.

对于导致该
的原因我完全不了解,不胜感激。

I am completely out of ideas as to what could cause this and would appreciate any help.

编辑1

ids.h

enum FileId{
    ID_file1ID=3,//just to see a non zero number in the debugger, which I do
    ID_file2ID,
    //and so on
    FileIdSize
}






编辑2


EDIT 2

这些错误开始时,编译器的行为异常异常。

When these errors start, the compiler starts to behave extremely unexpectedly.

添加行 sdfsdfgasaedfahjk 到任何文件仍会编译和通过。

Adding the line sdfsdfgasaedfahjk to any file STILL COMPILES AND PASSES.

它清楚地说明了将行添加到其中的文件名。
它明确指出了它的链接。
它过去了。

it clearly states the file name to which the line has been added to compiles. It clearly states it links to it. It passes.

我现在不信任编译器。

不知道会发生什么

推荐答案

您有2个cpp文件,它们定义了 FILEID 到值 3

You have 2 cpp files defining the FILEID to the same value 3.

对于MCVE:

ids.h:

#pragma once

#define File1 3
#define File2 3 //<--same value on purpose

global.h

struct Instance
{

};

struct Factory
{
    Instance getInstance(int FileID) { return Instance(); }
};

template <int ID>
struct Manager
{
    Factory factory;

    Instance& getInstance();
    Factory& getTheFactory() { return factory; }
};

template <>
Instance& Manager<FILEID>::getInstance()
{
    static Instance theInstance = getTheFactory().getInstance(FILEID);
    return theInstance;
};

name1.cpp

#include "ids.h"
#define FILEID File1   // The FileId corresponding to this file
#include "global.h"

name2.cpp

#include "ids.h"
#define FILEID File2   // The FileId corresponding to this file
#include "global.h"

在编译时, Manager< 3> :: getInstance(void)有一个特殊的实现 name1.cpp name2.cpp 创建的code>。

As this compiles there is a special implementation for Manager<3>::getInstance(void) created for both name1.cpp and name2.cpp.

不能在2个不同的编译单元中为 FILEID 使用相同的值。

You can't use the same value for FILEID in 2 different compilation units.

编辑:在编译时检查值

需要预处理器定义 __BASE_FILE __ =%(文件名)%(扩展名)

(配置属性-> C / C ++->预处理程序->预处理程序定义)

(Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions)

template <>
Instance& Manager<FILEID>::getInstance()
{
    #define _STR(x) #x
    #define STR(x) _STR(x)
    #define CHECK_ID() __pragma(message("Initializing \"Instance& Manager<FILEID>::getInstance()\" with FILEID="STR(FILEID)" in "STR(__BASE_FILE__)))
    CHECK_ID()
    static Instance theInstance = getTheFactory().getInstance(FILEID);
    return theInstance;
};

示例输出:

1>------Build started : Project : Test_Call, Configuration : Debug Win32------
1>  name1.cpp
1>  Initializing "Instance& Manager<FILEID>::getInstance()" with FILEID = FileId::ID_file1ID in "name1.cpp"
1>  name2.cpp
1>  Initializing "Instance& Manager<FILEID>::getInstance()" with FILEID = FileId::ID_file2ID in "name2.cpp"
1>  Test_Call.vcxproj-><Project>\Debug\Test_Call.exe
== == == == == Build: 1 succeeded, 0 failed, 0 up - to - date, 0 skipped == == == == ==






编辑:使用FileId值作为模板参数(MSVE)

id.h

#pragma once

enum FileId {
    ID_file1ID = 3,//just to see a non zero number in the debugger, which I do
    ID_file2ID,
    //and so on
    FileIdSize
};

global.h

#pragma once

#include "ids.h"

struct Instance
{

};

struct Factory
{
    Instance getInstance(int FileID) { return Instance(); }  
};

template <FileId ID>
struct Manager
{
    static const FileId manager_id = ID;        
    static Factory& getTheFactory() { return m_factory; }
    static Instance& getInstance()
    {
        static Instance theInstance = getTheFactory().getInstance(manager_id);
        return theInstance;
    }

private:
    static Factory m_factory;
};

global.cpp

#include "global.h"

Factory Manager<FileId::ID_file1ID>::m_factory;
Factory Manager<FileId::ID_file2ID>::m_factory;

name1.cpp

#include "global.h"

void test1()
{
    Instance& a = Manager<FileId::ID_file1ID>::getInstance();
}

name2.cpp

#include "global.h"

void test2()
{
    Instance& a = Manager<FileId::ID_file2ID>::getInstance();
}

test.cpp

#include <iostream>
#include "global.h"

using namespace std;


int main(int argc, char** argv)
{
    Instance& a = Manager<FileId::ID_file1ID>::getInstance();
    Instance& b = Manager<FileId::ID_file2ID>::getInstance();
    Instance& c = Manager<FileId::ID_file1ID>::getInstance();

    Instance* aptr = &a;
    Instance* bptr = &b;
    Instance* cptr = &c;

    printf("aptr==bptr -> %s\n", (aptr == bptr) ? "true" : "false"); //->false
    printf("aptr==cptr -> %s\n", (aptr == cptr) ? "true" : "false"); //->true (both use the instance from ID_file1ID
    printf("bptr==cptr -> %s\n", (bptr == cptr) ? "true" : "false"); //->false

}

这篇关于C ++ 03链接器“已经定义的符号”没有出现在中间文件上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆