Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

fatal error LNK1179: invalid or corrupt file: duplicate COMDAT '_IID_IXMLDOMImplementation'

I am getting this single error when I am linking my project,

COMMUNICATION.obj : fatal error LNK1179: invalid or corrupt file: duplicate COMDAT '_IID_IXMLDOMImplementation'

What is the source of the problem?

like image 932
Amit Pathak Avatar asked Aug 21 '12 11:08

Amit Pathak


3 Answers

This is a tricky one.

The issue is that the symbol(s)-generated is too-long, and an ambiguity exists:

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

In this case, the linker "sees" these two functions as the "same", because the part that makes them "unique" is longer-than-the-max-symbol length.

This can happen in at least three cases:

  • Your symbol names are "too-long" to be considered unique to the linker, but may have been fine for the compiler (such as when you expand-out from many nested templates)
  • You did some "trickery" that is invalid C++, and it passed the compiler, but you now have an invalid *.obj, and it chokes the linker.
  • You specified duplicate "unnamed" classes/structs, and the linker cannot resolve them.
  • ===[UPDATE]===, It's not your fault, it's an internal problem with the compiler and/or linker (see below for possible work-arounds).

Depending on the issue (above), you can "increase" your symbol-length (by limiting-your-decrease-of-symbol-length), or fix your code to make it valid (unambiguous) C++.

This error is (minimally) described by Microsoft at:

  • http://msdn.microsoft.com/en-us/library/cddbs9aw(v=vs.90).aspx

NOTE: This max-symbol-length can be set with the /H option, see: http://msdn.microsoft.com/en-us/library/bc2y4ddf(v=vs.90).aspx

  • RECOMMEND: Check to see if /H is used on your command-line. If it is, delete it (do not specify max-symbol-length, it will default to 2,047, the /H can only DECREASE this length, not increase it).

However, you probably triggered it through the /Gy option (function-level-linking), which was probably implied through one of /Z7, /Zi, or /ZI: http://msdn.microsoft.com/en-us/library/958x11bc(v=vs.90).aspx

One MSDN thread that talks about this issue is:

  • http://social.msdn.microsoft.com/Forums/en-US/vcmfcatl/thread/57e3207e-9fab-4b83-b264-79a8a717a8a7

This thread suggests that it's possible to trigger this issue with "invalid-C++-code-that-compiles" (you get your *.obj), but that invalid-*.obj chokes the linker (this example attempts to use main as both a function and as a template):

  • http://www.cplusplus.com/forum/lounge/46361/

===[UPDATE]===

I should have said this before, because I suspected, but I now have more information: It might not be your fault, there seems to be an issue in the compiler and/or linker that triggers this error. This is despite the fact that the only common denominator in all your failed relationships is you.

Recall that the "above-list" applies (it MIGHT be your fault). However, in the case where, "it's not your fault", here's the current-running-list (I'm confident this list is NOT complete).

  • There is an internal error/corruption in your *.ilk file (intermediate-link-file). Delete it and rebuild.
  • You have /INCREMENTAL turned on for linking, but somehow that incremental-linking is not working for your project, so you should turn it off and rebuild (Project-Properties=>Configuration Properties=>Linker=>General=>Enable Incremental Linking [set to "No" (/INCREMENTAL:NO)]
  • There's a problem with "Optimization" for "COMDAT Folding" in your use. Your can "Remove Redundant COMDATs" by going to Project Proerties=>Configuration Properties=>Linker=>Optimization=>Enable COMDAT Folding, set to "Remove Redundant COMDATs (/OPT:ICF)

Here's an interesting thread from a guy who sometimes can link, and sometimes not, by commenting in/out a couple lines of code. It's not the code that is the problem -- he just cannot link consistently, and it looks like the compiler and/or linker has an internal problem under some obscure use case:

  • http://www.pcreview.co.uk/forums/fatal-error-lnk1179-t1430593.html

Other observations from a non-trivial web search:

  • this problem appears to be non-rare
  • it seems to be related to some form of template<> use
  • others seem to see this problem with "Release" build when it did not have this problem with "Debug" build (but it is also seen on the "Debug" build in many cases)
  • if the link "fails" on one machine, it may "succeed" on another build machine (not sure why, a "clean-build" appears to have no effect)
  • if you comment in/out a particularly significant couple-lines-of-code, and finish your build, and keep doing this until all the code is un-commented again, your link may succeed (this appears to be repeatable)
  • if you get this error with MSVC2008, and you port your code to MSVC2010, you will still get this error

===[PETITION TO THE GOOD PEOPLE OF THE WORLD]===

If you have other observations on this error, please list them below (as other answers, or as comments below this answer). I have a similar problem, and it's not my fault, and none of these work-arounds worked for me (although they did appear to work for others in their projects in some cases).

I'm adding a bounty because this is driving me nuts.

===[UPDATE+2]===

(sigh), Here's more things to try (which apparently work for others, but did not work for me):

  • this guy changed his compile settings, and it worked (from thread at http://forums.codeguru.com/showthread.php?249603.html):

    Project->Settings->C++ tab, Debug cathegory: Inline function expansion: change from 'None' to 'Only _inline'.

  • the above thread references another thread where the had to re-install MSVC

  • it is possibly related to linking modules with "subtle-differences" in possibly-incompatible compiler and/or link switches. Check that all the "contributing libs" are built with the exact same switches

Here's some more symptoms/observations on this error/bug:

  • list(s) for above issues still apply
  • the issue seems to "start-showing-up" with MSVC2005, and continues with the same behavior for MSVC2008 and MSVC2010 (error still occurs after porting code to newer compilers)
  • restarting IDE, rebooting machine doesn't seem to work for anybody
  • one guy said an explicit "clean" followed by a recompile worked for him, but many others say it did not work for them
  • is often related to "incremental linking" (e.g., turn it off)

Status: No joy.

===[UPDATE+3 : LINK SUCCESS]===

Super-wacky-makes-no-sense fix to successfully link discovered!

This is a variation on (above), where you "fiddle-with-the-code-until-the-compiler-and/or-linker-behaves". NOT GOOD that one might need to do this.

Specific single linker-error (LNK1179) was for 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:

  • Convert MyMainBody<>() from a "template<>" to an explicit function, LINK SUCCESS.

THIS FIX SUX, as I need the EXACT-SAME-CODE for other types in other utilities, and the MyMainBody<>() implementation is non-trivial (but mostly simple) instantiations-and-setups that must be done in a specific way, in a specific order.

But hey, it's a temporary work-around for now: Confirmed on MSVC2008 and MSVC2010 compilers (same LNK1179 error for each, successful link on each after applying the work-around).

THIS IS A COMPILER AND/OR LINKER ERROR, as the code is "simple/proper-C++" (not even C++11).

So, I'm happy (that I got a link after suffering full-time for 2+weeks). But, disappointed (that the compiler and/or linker has a STUPID GLARING PROBLEM with linking a SIMPLE TEMPLATE<> in this use-case that I couldn't figure out how to address).

FURTHER, the "Bounty Ended", but nobody else wanted to take this on (no other answers?), so looks like "+100" goes to nobody. (heavy-sigh)

like image 131
charley Avatar answered Nov 20 '22 17:11

charley


This question has a lot of answers but none of them quite capture what was happening in my codebase, and what I suspect the OP was seeing back in 2012 when this question was asked.

The Problem

The COMDAT error on an IID_* type is easy to accidentally reproduce by using the #import directive with both the rename_namespace and named_guids attributes.

If two #imported type libraries contain the same interface, as is likely the case for OP's IXMLDOMImplementation, then the generated .tlh files will declare IID_IXMLDOMImplementation in both namespaces, leading to the duplicate.

For example, the code generated for:

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

...could be simplified into something like this:

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

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

Here's a simple RexTester reproduction of the problem: https://rextester.com/OLAC10112

The named_guids attribute causes the IID_* to be generated and the rename_namespace attribute wraps it in the namespace.

Unfortunately, in this case, extern "C" does not seem to work as expected when it appears inside a C++ namespace. This causes the compiler to generate multiple definitions for IID_FOOBAR in the same .obj file. DUMPBIN /SYMBOLS or a hex editor confirms the duplicate symbols.

The linker sees these multiple definitions and issues a duplicate COMDAT diagnostic.

A Solution

Knowing that rename_namespace doesn't play well with named_guids, the obvious solution is to simply not use them together. It's probably easiest to remove the named_guids attribute and instead use the _uuidof() operator.

After removing named_guids from #import directives and touching up the code, replacing all uses of FOO::IID_IFooBar with _uuidof(FOO::IFooBar), my COM-heavy codebase is back to building again.

like image 6
Sean Cline Avatar answered Nov 20 '22 16:11

Sean Cline


This issue is reported as a bug in some specific versions of Visual Studio 2017. Try patching 15.9.1 or later to fix this issue

  • Reported Issue in VS 15.8 Preview 4

  • Resolved patchs in VS 15.9 Preview 2

like image 1
DaBooba Avatar answered Nov 20 '22 16:11

DaBooba