【问题标题】:Link Error : xxx is already defined in *****.LIB :: What exactly is wrong?链接错误:xxx 已在 *****.LIB 中定义 :: 到底有什么问题?
【发布时间】:2010-04-27 23:18:49
【问题描述】:

问题:

我正在尝试使用一个名为 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 

文档:

这似乎是该库的一个常见错误,因此,他们确实有一个解决此问题的常见问题解答条目 (http://forum.dcmtk.org/viewtopic.php?t=35) 说:

  • 问题是链接器试图组合不同的, Visual 的不兼容版本 将 C++ 运行时库整合为单个 二进制。
  • 当您的项目和库的所有部分未完成时,就会发生这种情况 链接反对是用生成的 Visual 中相同的代码生成选项 C++。
  • 不要使用 /NODEFAULTLIB 解决方法,因为奇怪的软件 崩溃可能会随之而来。解决问题!

  • DCMTK 默认使用“多线程”或“多线程”编译 Debug”代码生成选项( 后者用于调试模式)。

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

为其他人解决相同问题:

Huge Amount of Linker Issues with Release Build Only 说:

看来您的发布版本是 试图链接到 内置调试。你可能有一个 构建中损坏的依赖项,(或 你错过了重建的东西 如果您的项目是手动释放 通常是分段构建的)。

从技术上讲,你似乎是 连接不同的项目 C Run Time library设置,一 用“多线程”,另一个 使用“多线程调试”。调整 所有项目的设置 使用相同的味道 图书馆和问题应该消失

问题:

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

  1. “调试模式”(多线程调试)和“发布模式”(多线程)是怎么回事? 究竟在幕后发生了什么?为什么正是这个东西导致了链接错误?

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

  3. 文档谈到“代码生成选项”。有哪些代码生成选项?他们是什么?

  4. 文档特别警告我们不要使用 /NODEFAULTLIB 解决方法。 (例如 /NODEFAULTLIB :msvcrt )。为什么?我怎么会惹麻烦?它到底是什么?

  5. 请为 MFC 用户解释文档中的最后一点。因为我将在这个项目的后面使用 MFC。解释我们为什么要这样做?如果我不这样做会造成什么麻烦。
  6. 您还有什么想说的吗?我的意思是关于类似的错误。我对 Linker 及其问题非常感兴趣。因此,如果有任何类似的事情,您可以提及它们或至少一些关键字。

【问题讨论】:

    标签: c++ c visual-c++ linker


    【解决方案1】:

    “调试模式”是怎么回事 (多线程调试)和“发布 模式”(多线程)?究竟是什么 发生在幕后?为什么 正是这件事导致了链接 错误?

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

    在链接时,所有对象文件和静态库文件中的对象的所有链接器选项都会组合在一起。如果请求了多个 CRT 库文件名,则链接器会读取所有这些文件名,并且您会遇到命名冲突,链接器不知道要使用哪一个。

    不知道有没有什么东西叫 “单线程调试”和 “单线程”再次导致 同样的事情。

    以前有,但最近几个版本的 Visual C++ 只提供了多线程兼容库。

    文档谈到了一些关于 “代码生成选项”。什么代码 代选项?他们是什么?

    inside your project options

    文档特别警告我们 不要使用 /NODEFAULTLIB 解决方法。 (例如 /NODEFAULTLIB :msvcrt )。为什么? 我怎么会惹麻烦?什么 到底是什么?

    如果您使用 /NODEFAULTLIB,则存储在对象文件和库中的对象中的所有链接器设置都会被忽略。您最终将没有运行时库,并且可能会丢失其他库。您可以手动将它们添加回来,但这仍然是一团糟。

    请解释最后一点 MFC 用户的文档。因为 稍后我将使用 MFC 项目。解释我们为什么要这样做? 如果我会造成什么麻烦 别。您还想做什么 提到?我的意思是关于类似的 错误。我对链接器很感兴趣 及其问题。所以,如果有 类似的事情你可以提到他们 或至少一些关键字。

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

    【讨论】:

      【解决方案2】:

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

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

      旧版本的 Visual Studio 过去除了多线程库(发布和调试版本)外,还具有单线程库(发布和调试版本)。对于您的项目,您可以假装单线程库从未存在过。

      如果您尝试使用随机方法来诱使链接器关闭并让您的客户而不是您自己发现问题,您可能会发现 /NODEFAULTLIB 选项可以做到这一点。 DCMTK 库的创建者警告您不要这样做,因为其他人过去做过同样愚蠢的事情。

      【讨论】:

        【解决方案3】:

        “调试模式”(多线程调试)和“发布模式”(多线程)是怎么回事?引擎盖下到底发生了什么?为什么这件事会导致链接错误?

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

        静态链接到 C 运行时通常不受欢迎,即使 Microsoft

        除了所有方法 上面描述的分发 Visual C++ 库 DLL,有 构建您的最后一个选项 不需要您的应用程序 分发DLL。然而,这 选项仅适用于本机代码 (/clr 不支持)和 认真地离开你的客户 容易受到任何安全漏洞的影响 也增加了很大的负担 自己修补所有客户系统 如果发现任何漏洞 的图书馆。这个选项是 在库中静态链接为 .lib 文件而不是动态 将它们加载为 DLL。你这样做 使用 cl.exe 上的 /MT 标志 命令行 (vs /MD),或选择 the appropriate option in your project Visual Studio 中的属性。你 可能希望使用此选项时 测试您的早期调试版本 之前在测试机上的应用 您开始进行设置。 [看 脚注 3]

        但是,我想不出任何场景 这实际上是正确的 运送产品时要做的事情 给客户。基本上,这是什么 方法是拉入二进制文件 编译时需要从 .LIB 文件中获取的代码 时间,使其成为您的 .exe 的一部分或 .dll 文件。它增加了 你的应用程序,没有办法 除了更新库 用新的重新编译你的应用程序 .LIB 和重新分配您的 重新申请。这是什么 意思是除非你去触摸 每台机器都有 每次都安装您的应用程序 存在安全漏洞 在 Visual C++ 库和 完全重新安装您的更新 二进制文件,你将离开你的 客户容易受到攻击。如果 相反,您每次都使用 DLL 存在安全漏洞 在 Visual C++ 库中找到, 微软将安装更新 通过集中进入 WinSxS 文件夹 Windows 更新和所有请求 DLL 将被重定向到 更新后的版本。这将删除所有 您身边的服务负担,也 允许用户安装一个小的 更新将触及他们所有的 应用程序而不是替换 每个安装的 exe 和 DLL 系统。请不要分发 通过链接构建的应用程序 静态地针对 Visual C++ 图书馆,除非你有一个系统 更新每个客户的地方 机器也有很好的 这样做的理由。这个时候,我可以 想不到在什么情况下 这是正确的做法 运输申请。


        不知道有没有什么东西叫 “单线程调试”和 “单线程”再次导致 同样的事情。

        没有,见上文。


        文档谈到“代码生成选项”。有哪些代码生成选项?他们是什么?

        右键单击您的 Visual C++ 项目(在 Visual Studio 中)并选择属性。在配置属性->C/C++->代码生成


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

        听从他们的建议,不要这样做。


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

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


        您还有什么想说的吗?我的意思是关于类似的错误。我对 Linker 及其问题非常感兴趣。因此,如果有任何类似的事情,您可以提及它们或至少一些关键字。

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

        【讨论】:

          猜你喜欢
          • 2012-01-19
          • 2020-02-11
          • 2012-10-06
          • 1970-01-01
          • 2016-03-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-13
          相关资源
          最近更新 更多