27

たとえば、GCC-4.6 と GCC-4.9 でコンパイルされた一連のライブラリを混在させることができます。

VS などのさまざまなコンパイラの「品種」は MinGW では使用できませんが、同じコンパイラの異なる世代は使用できますか? 問題が発生する可能性はありますか? もしそうなら何?

4

2 に答える 2

27

同じコンパイラの異なる世代が相互に互換性がある場合もありますが、常にそうとは限りませんたとえば、GCC 4.7.0は C/C++ ABIを変更しました。つまり、4.7.0+ と 4.7.0- でコンパイルされたライブラリは互いに互換性がない可能性があります (したがって、この例では、4.6 でコンパイルされたライブラリは4.9 でコンパイルされたライブラリと互換性があります)。GCC 4.7.0/4.7.1 で発生したように、特定のコンパイラ リリース内に ABI バグが存在する可能性もあります。

GCC バージョン 4.7.0 および 4.7.1 では C++ 標準ライブラリが変更され、C++11 モードの ABI に影響がありました。データ メンバーが std::list に追加され、そのサイズが変更され、一部のメンバー関数の定義が変更されました。 std::pair の move コンストラクターは自明ではなく、std::pair 引数または戻り値の型を持つ関数の呼び出し規約を変更していました。ABI の非互換性は GCC バージョン 4.7.2 で修正されましたが、その結果、GCC 4.7.0 または 4.7.1 でコンパイルされた C++11 コードは、異なる GCC バージョンおよび C++ でコンパイルされた C++11 コードと互換性がない可能性があります。任意のバージョンでコンパイルされた 98/C++03 コード。

GCC ABI ポリシーとガイドラインのページには、前方互換性を維持しようとしていることが示されていますが、後方互換性は維持されていません。

バージョン管理により、一連の以前のリリースとの互換性を維持しながら、ライブラリ バイナリの後続のリリースに新しいシンボルを追加して機能を追加する機能が提供されます。したがって、ライブラリ バイナリの最初のリリースにリンクされたプログラム バイナリは、ライブラリ バイナリが慎重に管理された後続のライブラリ バイナリに置き換えられた場合でも正しく実行されます。これは前方互換性と呼ばれます。

逆 (下位互換性) は当てはまりません。一連のリリースのライブラリ バイナリの最新バージョン (追加のシンボルが追加された) にリンクされたプログラム バイナリを取得し、ライブラリ バイナリの最初のリリースで置き換えて、リンクの互換性を維持することはできません。

このページには、GCC が特定のコンポーネントのさまざまなバージョンをマークするために使用するバージョン管理システムに関するかなり長い説明と、GCC 自体の背後にあるバージョン管理の説明もあります。

許可された変更

  • 次の例では、ライブラリのマイナー バージョン番号が「libstdc++.so.3.0.4」から「libstdc++.so.3.0.5」に増加します。

  • エクスポートされたグローバルまたは静的データ メンバーの追加

  • エクスポートされた関数、静的または非仮想メンバー関数の追加

  • 追加のインスタンス化によるエクスポートされたシンボルの追加

  • その他の許可された変更が可能です。

禁止されている変更

次の非網羅的なリストでは、ライブラリのメジャー バージョン番号が「libstdc++.so.3.0.4」から「libstdc++.so.4.0.0」に増加します。

  • gcc/g++ コンパイラ ABI の変更点

  • エクスポートされたシンボルのサイズの変更

  • エクスポートされたシンボルの配置の変更

  • エクスポートされたシンボルのレイアウトの変更

  • エクスポートされたシンボルのマングリングを変更する

  • エクスポートされたシンボルの削除

  • 基本クラスの追加または削除による型の継承プロパティの変更

  • C++ 標準で指定されている型のサイズ、配置、またはレイアウトを変更する。これらは、必ずしもライブラリ バイナリでインスタンス化またはエクスポートされるとは限りません。必要なすべてのロケール ファセットや、std::basic_streambuf などを含みます。

  • 暗黙的なバージョンを持つクラスに明示的なコピー コンストラクターまたはデストラクターを追加する。これにより、値渡しステートメントまたはパラメーターでコンパイラがこのクラスを処理する方法が変更されます。このクラスのインスタンスをレジスタで渡す代わりに、コンパイラは強制的にメモリを使用します。詳細については、C++ ABI ドキュメントの関数呼び出し規約と API に関するセクションを参照してください。

太字のビットに注意してください。完璧な世界では、同じメジャー リリース番号を持つ GCC バージョンはバイナリ互換です。これは完璧な世界ではないので、このようにコンパイラのバージョンを混在させる前に非常に慎重にテストしてください。しかし、一般的にはおそらく大丈夫でしょう。

于 2014-05-27T17:30:20.130 に答える
3

ABI (Application Binary Interface) と互換性がある場合、異なるコンパイラまたは同じコンパイラの異なるバージョンから生成されたバイナリ ファイルのみを混在させることができます。

次のようなもの:

  • 呼び出し手順
  • 名前マングリング
  • スレッドのローカル ストレージの処理

すべてABIの一部です。

これらのいずれかが変更されると、リンカー エラー、クラッシュ、またはその他の形式の予期しない動作が発生することがわかります。原則として、コンパイラ ベンダーは多くの場合、少なくとも古いバージョンとの後方互換性を維持しようとしますが、これを保証するものではありません。他の人が言ったように、ドキュメントを読むか、すべてを再コンパイルする必要があります。

于 2014-05-27T17:26:01.543 に答える