15

プロジェクトをリンクしているときに、この単一のエラーが発生します。

COMMUNICATION.obj : 致命的なエラー LNK1179: 無効または破損したファイル: 重複 COMDAT '_IID_IXMLDOMImplementation'

問題の原因は何ですか?

4

8 に答える 8

42

これはトリッキーです。

問題は、生成されたシンボルが長すぎて、あいまいさが存在することです。

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

この場合、リンカはこれら 2 つの関数を「同じ」と「認識」します。これは、それらを「一意」にする部分が最大シンボル長よりも長いためです。

これは、少なくとも3 つのケースで発生する可能性があります。

  • シンボル名が「長すぎる」ため、リンカーに固有のものと見なすことはできませんが、コンパイラにとっては問題ない可能性があります (多くのネストされたテンプレートから展開する場合など)。
  • 無効な C++ である「トリッキー」を実行し、コンパイラを通過しましたが、現在は無効*.objであり、リンカを詰まらせています。
  • 重複した「名前のない」クラス/構造体を指定しましたが、リンカーはそれらを解決できません。
  • ===[UPDATE]===、それはあなたのせいではなく、コンパイラやリンカの内部の問題です (可能な回避策については以下を参照してください)。

問題 (上記) に応じて、(シンボル長の減少を制限することによって) シンボル長を「増やす」か、コードを修正して有効な (明確な) C++ にすることができます。

このエラーは、Microsoft によって (最低限) 説明されています。

注:この max-symbol-length は/Hオプションで設定できます。次を参照してください: http://msdn.microsoft.com/en-us/library/bc2y4ddf(v=vs.90).aspx

  • 推奨:/Hコマンドラインで が使用されている かどうかを確認してください。そうである場合は、削除します (max-symbol-length を指定しないでください。デフォルトで になります。2,047は、この長さを減らす/Hことしかできず、増やすことはできません)。

ただし、オプション (function-level-linking) を介してトリガーした可能性があります。これは、、、またはのいずれか/Gyによって暗示されている可能性があります。 90).aspx/Z7/Zi/ZI

この問題について話している 1 つの MSDN スレッドは次のとおりです。

このスレッドは、「invalid-C++-code-that-c​​ompiles」でこの問題を引き起こす可能性があることを示唆していますが (あなたはあなたの を取得します*.obj)、invalid-*.objはリンカーをチョークします (この例mainでは、関数とテンプレートの両方として使用しようとしています) 。 :

===[更新]===

疑っていたので、以前にこれを言うべきでしたが、より多くの情報が得られました。あなたのせいではないかもしれません。このエラーをトリガーするコンパイラやリンカーに問題があるようです。これは、失敗したすべての関係の唯一の共通点があなたであるという事実にもかかわらずです.

「上記のリスト」が適用されることを思い出してください(それはあなたのせいかもしれません)。ただし、「あなたのせいではない」場合は、現在実行中のリストを次に示します (このリストは完全ではないと確信しています)。

  • *.ilkファイル (intermediate-link-file)に内部エラー/破損があります。削除して再構築してください。
  • リンクを/INCREMENTALオンにしましたが、何らかの形でそのインクリメンタル リンクがプロジェクトで機能しないため、オフにして再構築する必要があります ( Project-Properties=>Configuration Properties=>Linker=>General=>Enable Incremental Linking[「いいえ」に設定 ( /INCREMENTAL:NO)]
  • ご使用の「COMDAT 折りたたみ」の「最適化」に問題があります。に移動して、 「冗長な COMDAT を削除する」に設定すると、「冗長な COMDAT を削除する」ことができますProject Proerties=>Configuration Properties=>Linker=>Optimization=>Enable COMDAT Folding( /OPT:ICF)

これは、数行のコードをコメントイン/アウトすることで、リンクできる場合とできない場合がある人の興味深いスレッドです。問題はコードではありません - 彼は一貫してリンクできないだけで、コンパイラやリンカがいくつかのあいまいなユースケースで内部問題を抱えているようです:

重要なウェブ検索からのその他の観察:

  • この問題はまれではないようです
  • 何らかのtemplate<>用途に関係しているようです
  • 「デバッグ」ビルドではこの問題が発生しなかったのに、「リリース」ビルドではこの問題が発生するようです (ただし、多くの場合、「デバッグ」ビルドでも発生します)。
  • あるマシンでリンクが「失敗」した場合、別のビルド マシンでは「成功」する可能性があります (理由は不明ですが、「クリーン ビルド」は効果がないように見えます)。
  • 特に重要な数行のコードをコメントイン/アウトし、ビルドを終了し、すべてのコードが再びコメント解除されるまでこれを続けると、リンクが成功する可能性があります (これは繰り返し可能であるように見えます)。
  • MSVC2008 でこのエラーが発生し、コードを MSVC2010 に移植した場合でも、このエラーが発生します。

===[世界の善良な人々への請願]===

このエラーに関する他の観察結果がある場合は、それらを以下にリストしてください (他の回答として、またはこの回答の下のコメントとして)。私は同様の問題を抱えていますが、それは私のせいではありません.これらの回避策はどれもうまくいきませんでした.

これは私を狂わせているので、賞金を追加しています。

===[更新+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の再起動、マシンの再起動は誰にとってもうまくいかないようです
  • ある人は、明示的な「クリーン」とそれに続く再コンパイルがうまくいったと言いましたが、他の多くの人はそれがうまくいかなかったと言いました
  • 多くの場合、「インクリメンタル リンク」に関連しています (たとえば、オフにします)。

ステータス: 喜びがない。

===[UPDATE+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);
}

修正:

  • MyMainBody<>()" template<>" から明示的な関数 LINK SUCCESS に変換します。

THIS FIX SUX、他のユーティリティの他のタイプには EXACT-SAME-CODE が必要であり、MyMainBody<>()実装は特定の方法で特定の順序で実行する必要がある、重要な (しかしほとんど単純な) インスタンス化とセットアップであるためです。 .

しかし、今のところ一時的な回避策です。MSVC2008 および MSVC2010 コンパイラで確認されています (回避策をLNK1179適用した後、それぞれで同じエラーが発生し、リンクが成功しました)。

コードは「シンプル/適切な C++」(C++11 でさえない) であるため、これはコンパイラおよび/またはリンカーのエラーです。

だから、私は幸せです(フルタイムで2週間以上苦しんだ後、リンクを得たこと) . しかし、がっかりしました(コンパイラやリンカーには、このユースケースで SIMPLE TEMPLATE<> をリンクすることでSTUPID GLARING PROBLEMがあり、対処方法がわかりませんでした)

さらに、「Bounty Ended」ですが、誰もこれを取りたがりませんでした(他に答えはありませんか?)ので、「+100」は誰にも行きません。(ため息)

于 2012-11-21T14:16:08.480 に答える
4

この質問には多くの回答がありますが、私のコードベースで何が起こっていたのか、この質問が尋ねられたときに OP が 2012 年に見ていたと思われるものを完全に捉えているものはありません。

問題

型の COMDAT エラーは、との両方の属性を持つディレクティブIID_*を使用すると、誤って簡単に再現できます。#importrename_namespacenamed_guids

OP の場合のように、 2 つの#imported タイプ ライブラリに同じインターフェイスが含まれている場合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または、16 進エディタが重複シンボルを確認します。

リンカーはこれらの複数の定義を確認し、duplicate COMDAT診断を発行します。

解決策

rename_namespaceそれが とうまく機能しないことを知っているnamed_guidsので、明白な解決策は単純にそれらを一緒に使用しないことです。named_guids属性を削除し、代わりに_uuidof()operatorを使用するのがおそらく最も簡単です。

ディレクティブを削除named_guidsしてコードを修正し、すべての使用をに置き換えた後、COM を多用するコードベースは再びビルドに戻りました。#importFOO::IID_IFooBar_uuidof(FOO::IFooBar)

于 2018-10-22T18:45:51.163 に答える
0

私はc ++をしなければなりませんでした->コード生成->機能を有効にします-レベルリンク->いいえ

于 2015-12-27T10:33:21.833 に答える
0

私の不十分な回避策が誰かを助けることを願っています.すべての.objおよび中間ビルドファイル(少なくとも.pch、.pdb、.tlog、.lastbuildstate、および疑わしいと思われるものをすべて含む)を手動で削除し、最初から再構築します。

以前のビルドからいくつかのファイルが残っていると、問題がより頻繁に発生する傾向があるという証拠はありません。私の特定のビルド システムでは、.vcxproj ファイルと .sln ファイルも最初から削除して再作成します。

私自身の個人的な疑念は、ビルド/リンク プロセスで、中間ファイルが読み取られてから大規模なプロジェクトに書き込まれるまでの間に、ある種の競合状態が存在することです。繰り返しますが、これが真実であるという証拠はありませんが、バグの既知の事実すべてに当てはまると思われる唯一の推測です。

于 2016-02-16T02:16:44.723 に答える
0

MSVC から GCC にいくつかのコード (1) を移植しているときに、この問題が発生しました。ビルドを 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) {};
于 2013-08-29T08:21:57.027 に答える