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

Ami*_*hak 13 visual-studio-2005 visual-c++

当我链接项目时,我收到这个错误,

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

这个问题的根源是什么?

cha*_*ley 39

这是一个棘手的问题.

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

  //...
  void MyVeryLongFunctionNameUnique_0(void);
  void MyVeryLongFunctionNameUnique_1(void);
  //   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  //   (example max-symbol-length-seen-by-linker)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,链接器"看到"这两个函数为"相同",因为使它们"唯一"的部分长于最大符号长度.

至少在三种情况下会发生这种情况:

  • 您的符号名称"太长",不能被认为是链接器的唯一名称,但可能对编译器来说很好(例如,当您从许多嵌套模板展开时)
  • 你做了一些无效C++的"技巧",并且它通过了编译器,但你现在有一个无效的*.obj,它会扼杀链接器.
  • 您指定了重复的"未命名"类/结构,链接器无法解析它们.
  • === [更新] ===,这不是你的错,这是编译器和/或链接器的内部问题(参见下面的可能的解决方法).

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

此错误(最低限度)由Microsoft描述:

注意:可以使用/H选项设置此max-symbol-length ,请参阅:http://msdn.microsoft.com/en-us/library/bc2y4ddf(v = vs.90).aspx

  • 建议: 检查是否/H在命令行中使用了.如果是,删除它(不指定max-symbol-length,它将默认为2,047,/H只能递减此长度,不增加它).

不过,你可能通过触发它/Gy的选项(功能级联),这很可能是通过一个暗示/Z7,/Zi/ZI:http://msdn.microsoft.com/en-us/library/958x11bc(v=vs. 90)的.aspx

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

这个帖子暗示可以用"invalid-C++ - code-that- *.objcompiles "(你得到你的)来触发这个问题,但是这个无效 - 会*.obj阻塞链接器(这个例子试图main用作函数和模板) :

=== [UPDATE] ===

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

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

  • 文件中存在内部错误/损坏*.ilk(intermediate-link-file).删除它并重建.
  • 你已经/INCREMENTAL开启了链接,但不知何故增量链接对你的项目不起作用,所以你应该把它关掉并重建(Project-Properties=>Configuration Properties=>Linker=>General=>Enable Incremental Linking[设置为"No"(/INCREMENTAL:NO)]
  • 在使用中"COMDAT折叠"的"优化"存在问题.您可以通过转到Project Proerties=>Configuration Properties=>Linker=>Optimization=>Enable COMDAT Folding设置为"删除冗余COMDAT"来删除冗余COMDAT(/OPT:ICF)

这是一个有趣的线程来自一个有时可以链接,有时不通过注释/输出几行代码的人.这不是代码问题 - 他只是无法一致地链接,看起来编译器和/或链接器在一些不明确的用例下有一个内部问题:

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

  • 这个问题似乎并不罕见
  • 它似乎与某种形式的template<>使用有关
  • 其他人似乎看到"Release"构建时遇到"Debug"构建时没有这个问题的问题(但在很多情况下也可以在"Debug"构建中看到)
  • 如果一台机器上的链接"失败",它可能会在另一台构建机器上"成功"(不确定原因,"清理构建"似乎没有效果)
  • 如果你评论/输出一个特别重要的几行代码,并完成你的构建,并继续这样做,直到所有代码再次被注释,你的链接可能会成功(这似乎是可重复的)
  • 如果您在使用MSVC2008时出现此错误,并将代码移植到MSVC2010,则仍会出现此错误

=== [对世界上好人的请求] ===

如果您对此错误有其他意见,请在下面列出(作为其他答案,或作为此答案下方的评论).我有一个类似的问题,这不是我的错,这些解决方案都没有为我工作(尽管在某些情况下它们确实似乎在他们的项目中为其他人工作).

我正在加入赏金,因为这让我疯了.

=== [UPDATE + 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:链接成功] ===

发现成功链接的超级古怪 - 无意义修复!

这是(上面)的变体,在这里您可以"摆弄代码直到编译器和/或链接器行为".不好的是,人们可能需要这样做.

特定的单个链接器错误(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);
}
Run Code Online (Sandbox Code Playgroud)

固定:

  • 转换MyMainBody<>()从" template<>"一个明确的功能,连接成功.

这个修复SUX,因为我需要其他实用程序中的其他类型的EXACT-SAME-CODE,并且MyMainBody<>()实现是非平凡的(但大多数是简单的)实例化和设置,必须以特定的方式按特定顺序完成.

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

这是编译器和/或链接器错误,因为代码是"简单/适当的C++"(甚至不是C++ 11).

所以,我很高兴(我在全职工作2个星期后获得了一个链接).但是,很失望(编译器和/或链接器有一个STUPID GLARING PROBLEM,在这个用例中链接了一个SIMPLE TEMPLATE <>,我无法弄清楚如何解决).

更进一步,"Bounty结束",但没有其他人想要接受这个(没有其他答案?),所以看起来像" +100 "没有人.(重叹气)

  • 很棒的答案!+1 (2认同)

Sea*_*ine 8

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

问题

通过使用具有 和属性的指令IID_*,很容易意外地重现类型上的 COMDAT 错误。#importrename_namespacenamed_guids

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

例如,生成的代码为:

#import <foo.tlb> rename_namespace("FOO") named_guids;
#import <bar.tlb> rename_namespace("BAR") named_guids;
Run Code Online (Sandbox Code Playgroud)

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

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

namespace BAR {
    extern "C" __declspec(selectany) const GUID IID_IFOOBAR = {0};
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

一个办法

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

删除named_guidsfrom#import指令并修改代码,将所有使用替换为 后FOO::IID_IFooBar_uuidof(FOO::IFooBar)我的 COM 密集型代码库又重新开始构建。