链接错误:已经在*****中定义了xxx.LIB ::究竟出了什么问题?

问题:

我正在尝试使用名为DCMTK的库,该库使用了一些其他外部库(zlib,libtiff,libpng,libxml2,libiconv)。 我从同一个网站下载了这些外部库(* .LIB和* .h文件)。 现在,当我编译DCMTK库时,我收到链接错误(793错误),如下所示:

Error 2 error LNK2005: __encode_pointer already defined in MSVCRTD.lib(MSVCR90D.dll) LIBCMTD.lib dcmmkdir Error 3 error LNK2005: __decode_pointer already defined in MSVCRTD.lib(MSVCR90D.dll) LIBCMTD.lib dcmmkdir Error 4 error LNK2005: __CrtSetCheckCount already defined in MSVCRTD.lib(MSVCR90D.dll) LIBCMTD.lib dcmmkdir Error 5 error LNK2005: __invoke_watson already defined in MSVCRTD.lib(MSVCR90D.dll) LIBCMTD.lib dcmmkdir Error 6 error LNK2005: __errno already defined in MSVCRTD.lib(MSVCR90D.dll) LIBCMTD.lib dcmmkdir Error 7 error LNK2005: __configthreadlocale already defined in MSVCRTD.lib(MSVCR90D.dll) LIBCMTD.lib dcmmkdir Error 8 error LNK2005: _exit already defined in MSVCRTD.lib(MSVCR90D.dll) LIBCMTD.lib dcmmkdir 

文档:

这似乎是这个库的一个流行错误,所以,他们确实有一个解决这个问题的FAQ条目( http://forum.dcmtk.org/viewtopic.php?t=35 )说:

  • 问题是链接器尝试将不同的,不兼容的Visual C ++运行时库版本组合到一个二进制文件中。
  • 当并非项目的所有部分和链接的库都是使用Visual C ++中相同的代码生成选项生成的时,就会发生这种情况。
  • 不要使用/ NODEFAULTLIB解决方法,因为可能会出现奇怪的软件崩溃。 解决问题!

  • 默认情况下,DCMTK使用“multithreading”或“multithreading调试”代码生成选项(后者用于调试模式)进行编译。

  • 更改所有代码的项目设置以使用这些代码生成选项,
  • 或更改所有DCMTK模块的代码生成并重新编译。
  • MFC用户要注意:如果要将库链接到MFC应用程序,则应使用“multithreadingDLL”或“multithreadingDLL调试”设置编译DCMTK。

为他人解决同样的问题:

发布版本中大量链接器问题仅表示:

您的发布版本似乎正在尝试链接到构建调试的内容。 您的构建中可能存在破坏的依赖关系(或者如果您的项目通常是以碎片forms构建的,则您错过了重建某些东西以便手动释放)。

从技术上讲,您似乎将使用不同C Run Time library设置构建的项目链接起来,一个使用“Multi-Threaded”,另一个使用“Multi-Threaded Debug”。 调整所有项目的设置以使用库的相同风格,问题应该消失

问题:

到目前为止,我曾经认为Name mangling是唯一可能导致链接失败的问题,如果它没有被标准化的话。 刚才我知道还有其他的东西也会产生同样的效果。

  1. 怎么了“调试模式”(multithreading调试)和“发布模式”(multithreading)? 引擎盖下究竟发生了什么? 为什么这件事导致链接错误?

  2. 我想知道是否有一种叫做“单线程调试”和“单线程调试”的东西再次导致同样的事情。

  3. 文档讨论了“代码生成选项”。 什么代码生成选项? 他们是吗?

  4. 文档特别警告我们不要使用/ NODEFAULTLIB解决方法。 (示例/ NODEFAULTLIB:msvcrt)。 为什么? 我怎么会引起麻烦? 究竟是什么?

  5. 请解释MFC用户文档中的最后一点。 因为我将在本项目的后期使用MFC。 解释我们为什么要这样做? 如果我不这样做会导致什么麻烦。
  6. 还有什么你想提的吗? 我的意思是类似的错误。 我对Linker及其问题很感兴趣。 所以,如果有类似的东西,你可以提及它们或至少一些关键词。

怎么了“调试模式”(multithreading调试)和“发布模式”(multithreading)? 引擎盖下究竟发生了什么? 为什么这件事导致链接错误?

由于几个不同的原因,链接器拖入库中。 最简单的是,链接器命令行或链接器命令行上的链接器应答文件中列出了库。 但是,无论是在项目中编译还是打包到库中,任何目标文件都可以包含链接器选项,包括请求链接请求特定库。实际上,Visual C ++编译器会自动嵌入与编译时使用的项目选项相匹配的链接器选项。

在链接时,所有目标文件和静态库文件中的对象的所有链接器选项都会合并在一起。 如果请求了多个CRT库文件名,则链接器会读入所有这些文件名,并且它们会出现命名冲突,其中链接器不知道要使用哪个。

我想知道是否有一种叫做“单线程调试”和“单线程调试”的东西再次导致同样的事情。

曾经有过,但Visual C ++的最后几个版本只提供了multithreading兼容的库。

文档讨论了“代码生成选项”。 什么代码生成选项? 他们是吗?

查看项目选项 。

文档特别警告我们不要使用/ NODEFAULTLIB解决方法。 (示例/ NODEFAULTLIB:msvcrt)。 为什么? 我怎么会引起麻烦? 究竟是什么?

如果使用/ NODEFAULTLIB,则会忽略存储在目标文件和库中对象中的所有链接器设置。 您最终将没有运行时库,也许会遗漏其他库。 你可以手工添加它们,但它仍然是一个很大的混乱。

请解释MFC用户文档中的最后一点。 因为我将在本项目的后期使用MFC。 解释我们为什么要这样做? 如果我不这样做会导致什么麻烦。 还有什么你想提的吗? 我的意思是类似的错误。 我对Linker及其问题很感兴趣。 所以,如果有类似的东西,你可以提及它们或至少一些关键词。

MFC应用程序和MFC库必须使用相同的内存管理function,以便MFC分配的内存可以被应用程序释放,反之亦然。 FILE句柄和其他资源也是共享的。 MFC DLL已经编译为在DLL中使用CRT,并且为了能够共享资源,您需要使用相同的CRT,这也意味着使用DLL。

您需要配置项目属性,以便您的调试构建链接与DCMTK的调试版本以及您的版本构建链接与DCMTK的发布版本。

以上是你需要做的。 以下是您询问的其他一些随机事物的解释。

除了multithreading库(发布和调试版本)之外,旧版本的Visual Studio曾经拥有单线程库(发布和调试版本)。 对于您的项目,您可以假装从未存在单线程库。

如果您尝试使用随机方法欺骗链接器关闭并留下客户而不是自己发现的问题,您可能会发现/ NODEFAULTLIB选项会这样做。 DCMTK库的制造商警告你不要这样做,因为其他人过去做过同样愚蠢的事情。

怎么了“调试模式”(multithreading调试)和“发布模式”(multithreading)? 引擎盖下究竟发生了什么? 为什么这件事导致链接错误?

它们是C运行时库的不同版本。 您可以在调试和发布模式下静态链接到运行时库。 在代码生成选项(下面提到)中,那些将是“multithreading调试”和“multithreading”。 选项“Multi-Threaded Debug DLL”和“Multi-Threaded DLL”动态链接到C运行时。 通过动态链接到运行时,您还必须发送配置为安装VC可再发行组件包的安装程序,该软件包包含适用于您的Visual C ++版本的正确运行时dll。

静态链接到C运行时通常是不受欢迎的,即使是微软 :

除了上面描述的分发Visual C ++库DLL的所有方法之外,还有一个构建应用程序的最后一个选项,它不需要您分发DLL。 但是,此选项仅适用于纯本机代码(/ clr不支持)并且使您的客户严重容易受到任何安全漏洞的影响,并且如果发现漏洞,则会给您自己增加很大的负担来修补所有客户系统任何图书馆。 此选项将库中静态链接为.lib文件,而不是将它们动态加载为DLL。 您可以使用cl.exe命令行(vs / MD)上的/ MT标志,或通过Visual Studio在项目属性中选择适当的选项来执行此操作。 在开始设置之前,在测试机器上测试应用程序的早期调试版本时,您可能希望使用此选项。 [见脚注3]

但是,我认为在将产品运送给客户时,这实际上是不正确的事情。 基本上,这种方法的作用是在编译时从.LIB文件中提取所需的二进制代码,使其成为.exe或.dll文件的一部分。 它增加了应用程序的大小,除了使用新的.LIB重新编译应用程序并重新分发应用程序之外,无法更新库。 这意味着,除非您每次在Visual C ++库中发现安全漏洞并完全重新安装更新的二进制文件时触摸已安装应用程序的每台计算机,否则您将使您的客户容易受到攻击。 如果您使用DLL,则每次在Visual C ++库中发现安全漏洞时,Microsoft都会通过Windows Update将更新集中安装到WinSxS文件夹中,并且所有DLL请求都将重定向到更新版本。 这消除了您身边的所有服务负担,并允许用户安装一个小的更新,它将触及所有应用程序,而不是替换其系统上的每个已安装的exe和DLL。 请不要分发通过静态链接Visual C ++库构建的应用程序,除非您有一个系统来更新每个客户机器,并且还有一个非常好的理由这样做。 在这个时候,我认为没有任何情况下这对于运输应用来说是正确的。


我想知道是否有一种叫做“单线程调试”和“单线程调试”的东西再次导致同样的事情。

没有这样的事,见上文。


文档讨论了“代码生成选项”。 什么代码生成选项? 他们是吗?

右键单击Visual C ++项目(在Visual Studio中),然后选择“属性”。 在配置属性 – > C / C ++ – >代码生成下


文档特别警告我们不要使用/ NODEFAULTLIB解决方法。 (示例/ NODEFAULTLIB:msvcrt)。 为什么? 我怎么会引起麻烦? 究竟是什么?

听取他们的意见,不要这样做。


请解释MFC用户文档中的最后一点。 因为我将在本项目的后期使用MFC。 解释我们为什么要这样做? 如果我不这样做会导致什么麻烦。

由于MFC动态链接到C运行时,因此使用静态链接到C运行时的库将导致您在post中首先列出的链接器错误。


还有什么你想提的吗? 我的意思是类似的错误。 我对Linker及其问题很感兴趣。 所以,如果有类似的东西,你可以提及它们或至少一些关键词。

根据我的经验,始终动态链接到C运行时。 它通常可以为您节省很多麻烦,就像您现在遇到的那样。