4

Visual Studio Express 2008 を使用してコンパイルされた一連のコードを、Visual Studio 2003 でコンパイルされた .lib にリンクしようとしたときに、興味深い経験がありました。すべて C++ です。正確には、VS2003 で .lib にコンパイルされたSystemC 2.2.0 カーネルと、VS2008 でコンパイルされた SystemC モデルでした。

リンク時に、リンク中に SystemC.lib ファイル (つまり、VS2003 でコンパイルされたもの) からいくつかのシンボルが見つからないというエラーが発生し続けました。得られるエラーは次のとおりです(いくつかのバリエーションがあります):

SystemC.lib(sc_port.obj) : error LNK2001: unresolved external symbol "public: vo
id __thiscall std::_String_base::_Xran(void)const " (?_Xran@_String_base@std@@QB
EXXZ)

さまざまなリードから掘り下げた結果、.lib が期待する機能は次のとおりであることが判明しました。

Undecoration of :- "?_Xran@_String_base@std@@QBEXXZ"
is :- "public: void __thiscall std::_String_base::_Xran(void)const "

VS2008 がリンクしようとしていたライブラリ ファイル (libcpmt.lib) では、別の呼び出し規約が使用されていました。

Undecoration of :- "?_Xran@_String_base@std@@SAXXZ"
is :- "public: static void __cdecl std::_String_base::_Xran(void)"

この非互換性が発生した理由を突き止めようとしましたが、最終的にあきらめて、まったく同じ Visual Studio プロジェクトを VS2008 で再コンパイルし、VS2003 の SystemC.lib の代わりにその SystemC.lib を使用しました。これで、問題なく動作しました。

したがって、ここでの基本的な質問は、VS2003 から VS2008 への変更により、一部の関数の呼び出し規約が変更される原因となるのは何ですか? また、VS2003 コンパイルと同じ呼び出し規則を持つ関数を使用するために、VS2008 のリンカーに与える魔法のフラグはありますか?

更新、これまでの回答の要約: Microsoft が C++ (C ではなく C++ のみ) ABI を Visual Studio のメジャー バージョンから次のメジャー バージョンに変更する可能性が非常に高いです。ライブラリには、非互換性の原因となるその他の変更が含まれている場合もあります。最良のアドバイスは、VS の各バージョンの .lib を再コンパイルすることです。基本的には、ソースでユーザーに出荷し、ユーザーがたまたまインストールした VS のバージョンを使用してローカルでコンパイルするだけです。

基本的な問題は、次のアドバイスを使用して発見されました。

これらの質問はこの問題に答えていないことに注意してください。

4

2 に答える 2

3

C++ABIの標準はありません。これは、すべてのc ++コンパイラが異なるABIを処理できることを意味し、同じコンパイラの異なるバージョンが含まれています。Gccからの2つの異なるメジャーリリースで同じ問題が発生する可能性があります。このような変更は、リンク手順を改善する方法を見つけたときに発生する可能性があります。

しかし、ABIにはそれ以上のものが含まれます。たとえば、vtableが格納され、コンパイラによって生成されたコードによって内部で処理される方法。それが変更された場合、2008年に生成されたオブジェクトとコードは、2003年に行われた方法を期待してライブラリと互換性がなくなります。

この時点で、c ++ライブラリがソースコードとともに出荷されるのか、多くの異なるアーキテクチャやコンパイラでコンパイルされて出荷されるのかを理解できます。

通常、ライブラリを作成するときは、このような問題を回避するために、c++ではなくC言語でライブラリを開発します。Cには標準化されたABIが付属しているため、1つのコンパイラでコンパイルしてから、そのCABI標準を尊重する任意のCコンパイラとそのライブラリをリンクできます。たとえば、文字列の実装方法は標準であり、おそらく移動することはありません(悪名高いnullで終了する文字列)。std :: stringの実装は、あるGccメジャーリリースから別のリリースに変更されます(/ usr / include / c ++ / xx / bits / basic_stringファイルのbasic_stringクラスを確認してください)。

于 2009-08-13T14:25:11.900 に答える
2

私が知る限り、これらの問題は CRT ライブラリが原因で発生します。これらの問題はメジャー リリースで変更されるため、CRT の種類 (マルチスレッド、デバッグ、リリース、静的、動的など) を混在させないでください。

通常、CRT と動的にリンクすることで最小化できます。VS2005 で VS2003 ライブラリを再利用することに成功しましたが、面倒です。全体を再コンパイルすることをお勧めします。/NODEFAULTLIBコンパイラ フラグを使用して、問題を引き起こしている特定の CRT ライブラリとのリンクを回避できる場合があります。

于 2009-08-13T15:39:25.310 に答える