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

时间:2012-08-21 11:41:27

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

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

  

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

问题的根源是什么?

7 个答案:

答案 0 :(得分:39)

这是一个棘手的问题。

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

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

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

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

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

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

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

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

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

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

一个讨论此问题的MSDN主题是:

这个帖子暗示可以用"无效的C ++ - 代码 - 编译"来触发这个问题。 (你得到你的*.obj),但是那个无效 - *.obj会扼杀链接器(这个例子试图将main用作函数和模板):

<强> === [UPDATE] ===

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

回想一下&#34;上面的列表&#34;适用(可能是你的错)。但是,在这种情况下,&#34;这不是你的错误&#34;,这是当前的运行列表(我确信此列表未完成)。

  • *.ilk文件(intermediate-link-file)中存在内部错误/损坏。删除并重建。
  • 您已启用/INCREMENTAL进行关联,但不知何故增量链接对您的项目无效,因此您应将其关闭并重建(Project-Properties=>Configuration Properties=>Linker=>General=>Enable Incremental Linking [设为&#34;否& #34;(/INCREMENTAL:NO)]
  • &#34;优化问题&#34; for&#34; COMDAT Folding&#34;在你的使用。你可以&#34;删除冗余COMDAT&#34;转到Project Proerties=>Configuration Properties=>Linker=>Optimization=>Enable COMDAT Folding,设置为&#34;删除冗余COMDAT(/OPT:ICF

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

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

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

=== [对全世界人民的眷顾] ===

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

我加了赏金,因为这让我疯了。

<强> === [UPDATE + 2] ===

(叹气),这里有更多值得尝试的事情(这显然适用于其他人,但对我不起作用):

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

    Project->Settings->C++ tab, Debug cathegory: Inline function expansion:从&{39; None&#39;更改到&#39; Only _inline&#39;。

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

  • 它可能与将模块与“细微差异”联系起来。在可能不兼容的编译器和/或链接开关中。检查所有&#34;贡献的库和#34;使用完全相同的开关构建

这里有关于此错误/错误的更多症状/观察结果:

  • 上述问题的清单仍然适用
  • 这个问题似乎已经开始显现了#34;使用MSVC2005,并继续使用与MSVC2008和MSVC2010相同的行为(将代码移植到新编译器后仍然出现错误)
  • 重新启动IDE,重新启动计算机似乎不适用于任何人
  • 一个人说清楚&#34;清洁&#34;然后重新编译为他工作,但许多人说它不适合他们
  • 通常与&#34;增量链接相关&#34; (例如,将其关闭)

状态:没有快乐。

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

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

这是(上面)的一个变体,在这里您可以使用代码,而不是编译器和/或链接器行为&#34;。不好的是,人们可能需要这样做。

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

THE FIX:

  • 转换MyMainBody<>()来自&#34; template<>&#34;到显式功能,LINK SUCCESS

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

但是,嘿,它暂时是临时解决方案:在MSVC2008和MSVC2010编译器上确认(每个成功链接相同LNK1179错误,在应用解决方法之后每个成功链接。)

这是编译器和/或链接器错误,因为代码是&#34; simple / proper-C ++&#34; (甚至不是C ++ 11)。

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

进一步,&#34; Bounty结束&#34; ,但没有其他人想在(没有其他答案?)上采取这个,所以看起来像&# 34;的 100 &#34;没人去。 (重叹气)

答案 1 :(得分:1)

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

问题

通过同时使用具有#import directiverename_namespace属性的named_guids,很容易意外地产生IID_*类型的COMDAT错误。

如果两个#import类型的类型库包含相同的接口(就像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 ++名称空间中时,似乎无法按预期工作。这将导致编译器在同一IID_FOOBAR文件中为.obj生成多个定义。 DUMPBIN /SYMBOLS或十六进制编辑器确认重复的符号。

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

解决方案

知道rename_namespacenamed_guids搭配不好,显而易见的解决方案是不将它们一起使用。删除named_guids属性,而使用_uuidof() operator可能是最简单的。

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

答案 2 :(得分:1)

在某些特定版本的Visual Studio 2017中,此问题被报告为错误。尝试修补15.9.1或更高版本可解决此问题

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

我必须这样做 c ++ - &gt;代码生成 - &gt;启用功能 - 级别链接 - &gt;无

答案 5 :(得分:0)

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

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

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

答案 6 :(得分:0)

几年前我写过Outlook插件,我被要求写另一个。马上,我遇到了这个问题,通过一个消除过程,我修好了我的。

事实证明,当您选择一个extensibity项目(我在当天手工编码)时,它会创建并保存我不知道的两个对象: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

在徘徊修复编译错误后,编译和链接就好了。我并不是说这对所有人都有用,但它对我有用。祝所有经过这里的人好运....