VC8 to VC10 - LNK2005 errors

VC8 to VC10 - LNK2005 errors

本文关键字:LNK2005 errors VC10 to VC8      更新时间:2023-10-16

我最近安装了Visual Studio 2010,并使用CMake为我的项目生成解决方案文件。

我遇到的第一个问题是因为新的"移动构造函数",所以我不得不从我的代码中删除一些隐式转换—很好,现在可以了。

我目前的情况是:我正在编译DLL 1,它只依赖于一些系统库(Kernel32等)和CRT,以及DLL 2,它链接到DLL 1,以及一些第三方库。

我得到的错误如下:
DLL1.lib(DLL1.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) already defined in objFromDLL2.obj

这似乎正是这里所描述的问题。

然而,这个线程没有解决我的问题。

  • 我已经确认DLL1和DLL2是用/MD代码生成标志编译的,
  • DLL2链接到squish, glow和devil —我已经手动重新编译了所有这些和任何库,它们依赖于VC10的,也与/MD
  • edit根据本文(这与我的问题类似),我已经删除了从std:: containers
  • 派生的类的任何实例
  • 编辑我已经确认这不是第三方问题,因为我已经使用同一套库成功编译了另一个项目,但是我仍然无法编译我的原始项目
  • edit dllexport在我的代码中被用于所有需要的地方

我错过了什么?如果我需要提供更多的信息,请让我知道,我会尽我所能编辑问题。

update:已经有一段时间了,我仍然没有解决方案。我一直在更新对评论的回应问题,我目前正在研究一个不同的代码库,它确实有效-我开始认为旧代码的向后兼容性终于开始枯竭,我应该继续前进。

more update:我发现了一个可能非常不受欢迎的链接标志,/FORCE:MULTIPLE,它通过忽略除第一个符号定义外的所有符号,将错误转换为警告。这样做肯定会有不好的副作用。对该标志的测试突出显示了LNK2001: unresolved std::string::npos,它隐藏在之前的所有LNK2005错误中。折磨永无止尽

我已经成功使用了/FORCE:MULTIPLE。在使用混合库时,有时这是不可避免的。只要链接器使用1 &相同的地址一致地解析引用,它有效。其他定义将被忽略。

我倾向于认为你所说的假设是不正确的。特别是,"DLL 1,它只依赖于一些系统库(Kernel32等)",如果它用/MD编译并引用std::string::~string,就不可能是正确的。这显然会导致对CRT的依赖。

另外,如果DLL1不依赖DLL2,那么链接器是如何感知来自DLL2的文件的呢?你是否碰巧建立了一个循环依赖?

在VS2008和VS2010之间,std::string::~string似乎从CRT中被移除。因此,它不再是您自己代码的DLLimport。这可以解释行为上的差异。DLL1和DLL2之间的循环依赖关系对std::string::~string来说无关紧要,因为两者都将从CRT获得它,而这显然不是循环的一部分。

似乎问题是DLL1确实导出std::string(可能隐式地,因为它是在一个类中使用,也导出),但DLL1的头没有声明。因此,在编译DLL2时,它不会被标记为导入。这没有问题,因为它是一个模板:编译器只是实例化了另一个副本。但是随后链接器出错了,因为DLL2实际上应该导入std::string

解决方案:显式export/import std::string;您可能已经在DLL1头文件中为_declspec( )设置了合适的宏。