【问题标题】:fatal error LNK1179: invalid or corrupt file: duplicate COMDAT '_IID_IXMLDOMImplementation'致命错误 LNK1179:无效或损坏的文件:重复的 COMDAT '_IID_IXMLDOMImplementation'
【发布时间】:2012-08-21 11:41:27
【问题描述】:

我在链接我的项目时遇到了这个错误,

COMMUNICATION.obj:致命错误 LNK1179:文件无效或损坏: 重复 COMDAT '_IID_IXMLDOMImplementation'

问题的根源是什么?

【问题讨论】:

  • 您是否尝试过删除 COMMUNICATION.obj 并重建?
  • 是的,我做到了,但是重新创建了相同的文件,并且再次给出了相同的错误。

标签: visual-c++ visual-studio-2005


【解决方案1】:

这是一个棘手的问题。

问题是生成的符号太长,存在歧义:

  //...
  void MyVeryLongFunctionNameUnique_0(void);
  void MyVeryLongFunctionNameUnique_1(void);
  //   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  //   (example max-symbol-length-seen-by-linker)

在这种情况下,链接器将这两个函数“视为”“相同”,因为使它们“唯一”的部分比最大符号长度长。

这可能发生在至少三种情况:

  • 您的符号名称“太长”而不能被认为是链接器独有的,但对于编译器来说可能没问题(例如当您从许多嵌套模板中展开时)
  • 您做了一些无效 C++ 的“诡计”,它通过了编译器,但您现在有一个无效的 *.obj,它阻塞了链接器。
  • 您指定了重复的“未命名”类/结构,链接器无法解析它们。
  • ===[UPDATE]===,这不是你的错,这是编译器和/或链接器的内部问题(请参阅下文了解可能的解决方法)。

根据问题(如上),您可以“增加”符号长度(通过限制符号长度的减少),或修复代码以使其有效(明确)C++。

Microsoft 在以下位置(最少)描述了此错误:

注意:此最大符号长度可以使用/H 选项设置,请参阅:http://msdn.microsoft.com/en-us/library/bc2y4ddf(v=vs.90).aspx

  • 建议: 检查您的命令行上是否使用了/H。如果是,删除它(不指定max-symbol-length,默认为2,047/H只能DECREASE这个长度,不能增加它)。

但是,您可能通过/Gy 选项(函数级链接)触发了它,这可能是通过/Z7/Zi/ZI 之一隐含的:http://msdn.microsoft.com/en-us/library/958x11bc(v=vs.90).aspx

讨论此问题的一个 MSDN 线程是:

这个线程表明可以使用“invalid-C++-code-that-c​​ompiles”触发这个问题(你得到你的*.obj),但是那个invalid-*.obj会阻塞链接器(这个例子试图使用main 既作为函数又作为模板):

===[更新]===

我之前应该说这个,因为我怀疑,但我现在有更多信息:这可能不是你的错,编译器和/或链接器中似乎存在触发此错误的问题。尽管事实上所有失败的关系中唯一的共同点就是你自己。

回想一下“上面的列表”适用(这可能是你的错)。但是,在“这不是你的错”的情况下,这里是当前运行列表(我相信这个列表不完整)。

  • *.ilk 文件(中间链接文件)中存在内部错误/损坏。删除并重建。
  • 您已为链接打开了/INCREMENTAL,但不知何故增量链接不适用于您的项目,因此您应该将其关闭并重建 (Project-Properties=>Configuration Properties=>Linker=>General=>Enable Incremental Linking [设置为“否”(/INCREMENTAL:NO)]
  • 在您的使用中,“COMDAT 折叠”的“优化”存在问题。您可以通过转到 Project Proerties=>Configuration Properties=>Linker=>Optimization=>Enable COMDAT Folding 来“删除冗余 COMDATs”,设置为“删除冗余 COMDATs (/OPT:ICF)

这是一个有趣的线程,来自一个有时可以链接,有时不能,通过注释/注释几行代码。问题不是代码——他只是无法一致地链接,而且看起来编译器和/或链接器在一些晦涩的用例下存在内部问题:

来自非平凡网络搜索的其他观察结果:

  • 这个问题似乎并不罕见
  • 它似乎与某种形式的template<> 使用有关
  • 其他人似乎在“发布”版本中看到此问题,而“调试”版本没有此问题(但在许多情况下,“调试”版本中也有此问题)
  • 如果链接在一台机器上“失败”,它可能在另一台构建机器上“成功”(不知道为什么,“干净构建”似乎没有效果)
  • 如果您注释/注释掉特别重要的几行代码,并完成构建,并继续这样做,直到所有代码再次取消注释,您的链接可能会成功(这似乎是可重复的)
  • 如果您在使用 MSVC2008 时遇到此错误,并且您将代码移植到 MSVC2010,您仍然会收到此错误

===[致全世界好人的请愿书]===

如果您对此错误有其他意见,请在下面列出(作为其他答案,或作为此答案下方的 cmets)。我有一个类似的问题,这不是我的错,而且这些变通方法都不适合我(尽管在某些情况下它们似乎确实适用于其他人的项目)。

我正在添加赏金,因为这让我发疯了。

===[更新+2]===

(叹气),还有更多可以尝试的方法(显然对其他人有用,但对我无效):

  • 这家伙改变了他的编译设置,并且它起作用了(来自http://forums.codeguru.com/showthread.php?249603.html的线程):

    Project->Settings->C++ tab, Debug cathegory: Inline function expansion:从“None”更改为“Only _inline”。

  • 上面的线程引用了另一个必须重新安装 MSVC 的线程

  • 这可能与在可能不兼容的编译器和/或链接开关中链接具有“细微差异”的模块有关。检查所有“贡献库”是否使用完全相同的开关构建

以下是有关此错误/错误的更多症状/观察结果:

  • 上述问题的列表仍然适用
  • 问题似乎在 MSVC2005 中“开始出现”,并且在 MSVC2008 和 MSVC2010 中继续出现相同的行为(将代码移植到较新的编译器后仍然会出现错误)
  • 重启 IDE,重启机器似乎对任何人都不起作用
  • 一个人说明确的“清理”然后重新编译对他有用,但许多其他人说这对他们不起作用
  • 通常与“增量链接”相关(例如,将其关闭)

状态:不开心。

===[更新+3:链接成功]===

Super-wacky-makes-no-sense 修复成功发现链接!

这是(上图)的一种变体,您可以“摆弄代码直到编译器和/或链接器行为”。可能需要这样做并不好。

特定的单个链接器错误 (LNK1179) 用于 MyMainBody<>()

#include "MyClassA.hpp"
#include "MyClassB.hpp"
#include "MyClassC.hpp"
#include "MyClassD.hpp"
#include "MyMainBody.hpp"

int main(int argc, char* argv[])
{
  // Use a function template for the "main-body", 
  // implementation is "mostly-simple", instantiates 
  // some local "MyClass" instances, they reference 
  // each other, and do some initialization,
  // (~50 lines of code)
  //
  // !!! LNK1179 for `MyMainBody<>()`, mangled name is ~236 chars
  //
  return MyMainBody<MyClassA,MyClassB,MyClassC,MyClassD>(argc,argv);
}

修复:

  • MyMainBody&lt;&gt;()从“template&lt;&gt;”转换为显式函数,LINK SUCCESS

这个 FIX SUX,因为我需要 EXACT-SAME-CODE 用于其他实用程序中的其他类型,并且 MyMainBody&lt;&gt;() 实现是不平凡的(但大多是简单的)实例化和设置这必须以特定的方式,以特定的顺序完成。

但是,嘿,现在这是一个临时解决方法:在 MSVC2008 和 MSVC2010 编译器上得到确认(每个都相同的 LNK1179 错误,在应用解决方法后每个都成功链接)。

这是编译器和/或链接器错误,因为代码是“简单/正确的 C++”(甚至不是 C++11)。

所以,我很高兴(在全职工作 2 周以上后,我得到了一个链接)。但是,很失望(编译器和/或链接器有一个愚蠢的问题,在这个用例中链接一个简单的模板,我无法弄清楚如何解决)

进一步,“赏金结束”,但没有其他人愿意接受这个(没有其他答案?),所以看起来像“+100”没有人。 (沉重的叹息)

【讨论】:

  • 我刚刚在 VC.NET SP1 上遇到过这个问题。我使用相同的类型库导入来实现两个 COM coclass,所以我只想实现一个包装器,所以我使用了属性 ..rename_namespace("CleanerName"), named_guids, no_implementation 并将其放在 stdafx.h 中,然后使用 ..@987654360 @ 在 CPP 文件中。然后,我在其中一个 IID 定义上得到了您的错误。当我将它移到 stdafx.h 以外的地方时,错误就消失了。
  • 指定 /Ob1 或 /Ob2(启用内联)对我有用
  • 但是指定内联与某些调试标志不兼容,所以就我而言,我不得不简化代码。
  • 这个 bug 在 VS 2015 的 Chrome 中随着频率的增加而发生 - 也许是这个 bug 的新变种? connect.microsoft.com/VisualStudio/feedback/details/1853228/…
  • 两年后;使用 named_guids 导入类型库有时会导致这种情况。
【解决方案2】:

这个问题有很多答案,但没有一个能完全捕捉到我的代码库中发生的事情,以及我怀疑 OP 在 2012 年被问到这个问题时看到的情况。

问题

#import directive 同时带有rename_namespacenamed_guids 属性,很容易意外重现IID_* 类型的COMDAT 错误。

如果两个#imported 类型库包含相同的接口,就像OP 的IXMLDOMImplementation 的情况一样,那么生成的.tlh 文件将在两个命名空间中声明IID_IXMLDOMImplementation,从而导致重复。

例如生成的代码:

#import <foo.tlb> rename_namespace("FOO") named_guids;
#import <bar.tlb> rename_namespace("BAR") named_guids;

...可以简化成这样的:

namespace FOO {
    extern "C" __declspec(selectany) const GUID IID_IFOOBAR = {0};
}

namespace BAR {
    extern "C" __declspec(selectany) const GUID IID_IFOOBAR = {0};
}

这是问题的简单 RexTester 重现:https://rextester.com/OLAC10112

named_guids 属性导致生成 IID_*rename_namespace 属性将其包装在命名空间中。

不幸的是,在这种情况下,extern "C" 在出现在 C++ 命名空间中时似乎无法按预期工作。这会导致编译器在同一个.obj 文件中为IID_FOOBAR 生成多个定义。 DUMPBIN /SYMBOLS 或十六进制编辑器确认重复的符号。

链接器看到这些多个定义并发出duplicate COMDAT 诊断。

解决方案

知道rename_namespace 不能很好地与named_guids 配合使用,显而易见的解决方案就是不要一起使用它们。删除named_guids 属性并改用_uuidof() operator 可能是最简单的方法。

在从#import 指令中删除named_guids 并修改代码后,将FOO::IID_IFooBar 的所有用法替换为_uuidof(FOO::IFooBar),我的繁重的COM 代码库又重新开始构建了。

【讨论】:

  • 几年前我赞成这个答案。刚刚再次遇到这个问题,发现自己在这里。希望我能再次投票,谢谢!
  • 我又来了。希望我能再次对此表示赞同。谢谢!
【解决方案3】:

此问题在 Visual Studio 2017 的某些特定版本中报告为错误。请尝试修补 15.9.1 或更高版本以修复此问题

【讨论】:

    【解决方案4】:

    我在将一些代码 (1) 从 MSVC 移植到 GCC 时遇到了这个问题。为了让构建链接到 GCC,我必须为一些专门的模板函数 (2) 提供空实现,这导致了 MSVC 上的 LNK1179。我能够通过内联函数 (3) 来解决,即

    1. template&lt;&gt; template&lt;&gt; void LongName1&lt;LongName2&gt;::FunctionName(boost::library::type1 &amp; a, const unsigned int b);
    2. template&lt;&gt; template&lt;&gt; void LongName1&lt;LongName2&gt;::FunctionName(boost::library::type1 &amp; a, const unsigned int b) {};
    3. template&lt;&gt; template&lt;&gt; inline void LongName1&lt;LongName2&gt;::FunctionName(boost::library::type1 &amp; a, const unsigned int b) {};

    【讨论】:

      【解决方案5】:

      我不得不做 c++ -> 代码生成 -> 启用函数 - 级别链接 -> 否

      【讨论】:

      • 这并没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方发表评论 - 您可以随时评论自己的帖子,一旦您有足够的reputation,您就可以comment on any post。 - From Review
      • 谢谢!我不习惯 Stackoverflow。无论如何我无法回答作者,因为我不明白问题的根源。所以我只是公开了一个我发现的解决方案,如果对某人有用。
      【解决方案6】:

      希望我蹩脚的解决方法可以帮助某人:我确保手动删除所有 .obj 和中间构建文件(至少包括 .pch、.pdb、.tlog、.lastbuildstate 和其他任何看起来可疑的东西)并重建从头开始。

      我建议在没有证据的情况下,从以前的构建中遗留一些文件往往会导致问题更频繁地发生。在我的特定构建系统中,我也从头开始删除并重新创建 .vcxproj 和 .sln 文件。

      我个人的怀疑是,在读取中间文件和将它们写入大型项目之间的构建/链接过程中存在某种竞争条件。同样,我没有证据证明这是真的,但这是我唯一的猜测,似乎符合该错误的所有已知事实。

      【讨论】:

        【解决方案7】:

        几年前我编写了 Outlook 插件,并被要求编写另一个插件。马上,我就遇到了这个问题,通过一个小小的排除过程,我解决了我的问题。

        事实证明,当您选择一个可扩展性项目时(我以前手工编写了自己的代码),它会创建并保存 2 个我不知道的对象:DTE 和 DTE80。为了创建操作这些对象的接口,它们直接从 stdafx.h 中的 DLL 导入。由于我正在使用 Outlook,我还需要导入几个界面:Office 和 Outlook。

        所以,看到这个错误几乎是在编写我的第一段代码后立即弹出,我重新开始,一次添加一个东西。在我添加之后,该项目以所述方式炸毁了块:

        //Added mvc 
        //The following #import imports MSO based on it's LIBID
        #import "libid:2DF8D04C-5BFA-101B-BDE5-00AA0044DE52" version("2.2") lcid("0") rename_namespace("Office") raw_interfaces_only named_guids
        using namespace Office;
        
        //The following #import imports Outoloks Object lib based on it's LIBID
        #import "libid:00062FFF-0000-0000-C000-000000000046" rename_namespace("Outlook") raw_interfaces_only named_guids 
        using namespace Outlook;
        

        因此,鉴于我无意弄清楚 DTE 的内容,我只是将它们以及与它们有关的任何内容都注释掉了:

        //The following #import imports VS Command Bars based on it's LIBID
        //  #import "libid:1CBA492E-7263-47BB-87FE-639000619B15" version("8.0") lcid("0") raw_interfaces_only named_guids
        
        //The following #import imports DTE based on it's LIBID
        //  #import "libid:80cc9f66-e7d8-4ddd-85b6-d9e6cd0e93e2" version("8.0") lcid("0") raw_interfaces_only named_guids
        
        //The following #import imports DTE80 based on it's LIBID
        //  #import "libid:1A31287A-4D7D-413e-8E32-3B374931BD89" version("8.0") lcid("0") raw_interfaces_only named_guids
        

        在修复编译错误后,它编译和链接得很好。我并不是说这对每个人都有效,但它对我有用。祝所有路过这里的人好运......

        【讨论】:

          【解决方案8】:

          我收到了这个错误并且对此感到非常困惑。结束注释掉引用的 cpp 中的所有内容并小批量重新引入内容,直到文件恢复到与我开始时相同的状态。而且我不再收到错误消息。对我来说,这在我的情况下表明这是编译器中的一个错误,但由于我无法再重现它,所以我无法获得更多帮助。

          我在: 微软 Visual Studio 专业版 2019 版本 16.11.3

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-11-29
            • 2013-04-28
            • 1970-01-01
            • 2020-03-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-07-29
            相关资源
            最近更新 更多