(C)異なるコンパイラで作成されたオブジェクトファイルはバイナリ互換ですか?


11

C ++コンパイラは互いに互換性がないことを理解しています。ただし、特にCについては、このトピックに関する情報を見つけることができませんでした。私は、C標準にはコンパイラが適切に実装できる余地を残していることを知っています。たとえば、ほとんどの(すべて?)データ型のサイズとアライメントは、最小限の保証のために実装定義で保存されます。したがって、2つのコンパイラー(または同じコンパイラーの2つのバージョン)は、多くの詳細について意見が一致しません。

異なるコンパイラでコンパイルされた2つのオブジェクトファイルが実際に適切にリンクされるという保証はないという考え方で正しいですか?たとえば、ポインタのサイズは、一方のオブジェクトファイルでは32ビット、もう一方のファイルでは64ビットになります。しかし、そうだとすると、なぜCライブラリはプリコンパイルされた形で配布されるのでしょうか?私が使用したのと同じコンパイラー(例えばgcc)を使用する、またはバイナリー互換性を確保するために使用されている事実上の標準を使用するという期待はありますか?そして、C言語オブジェクトファイルとリンクするときに、外国語インターフェイスを備えた他の言語は、物事が適切に整列することをどのように保証しますか?


覚えている限り、Cオブジェクトファイルは、同じプラットフォーム用にコンパイルされている限り、相互に互換性がある必要があります。オブジェクトファイルは、モジュール内の各シンボルにアクセスするために使用できるシンボルテーブルを持つロード可能なバイナリコードを含む単なるアーカイブです。
ジョルジオ14

2
ライブラリは互換性を持たせることができ、objが保証されるとは思わない
ラチェットフリーク14

@Giorgo「同じプラットフォーム」とは、CPUアーキテクチャまたはCPUアーキテクチャ+ OSのことですか?
ドーバル14

@ratchetfreak私は、ライブラリはほとんどの場合、複数のオブジェクトファイルの連結であるという印象を受けていました。それは間違っていますか?
ドーバル14

オブジェクトが異なるコンパイラ間で互換性があるとは思わないでしょう。
old_timer 14

回答:


10

一般的な答えは「いいえ」です。C言語コンパイラは相互に互換性がありません。C言語標準は、いかなる種類のバイナリ相互運用性も定義しておらず、ほとんどのコンパイラ作成者は試してさえいません。

私はそれを修飾する必要があります。Cコンパイラによって発行されたオブジェクトは、実行可能ライブラリまたは実行時リンク可能ライブラリを生成するために、実行時ライブラリとリンクする必要があります。Cランタイムライブラリによって提供される可視関数は互換性があるはずですが、実装に固有で相互運用性を妨げる非可視関数もあります。

この互換性の欠如は、同じコンパイラの異なるバージョンにも拡張されます。一般に、古いバージョンと新しいバージョンのコンパイラでコンパイルされたプログラムとライブラリは一緒にリンクできず、MSVCでコンパイルされたプログラムとライブラリはGCCでコンパイルされたものとリンクできません。

特定の非常に便利な例外があります。すべてのプラットフォームは、動的リンクABI(Application Binary Interface)と、そのABIに準拠できる任意の言語のプログラムに互換性があります。そのため、MSVC(または他の何か)を使用してDLL(Windows)をビルドし、異なるバージョンのMSVCまたはGCCによってコンパイルされたプログラムから呼び出すことができます。

Windowsには他に2つのABIがあります。COMおよび.NETアセンブリであり、それらは幅広い言語に対応しています。したがって、相互運用性は確かに可能ですが、互換性はありません。


リンカマップを比較すると、非互換性の程度を簡単に確認できます。GNU用ld -M、MSVC用link /map。生成された2つのファイルを調べます。どちらにもprintfやmainなどの名前が認識されますが、(オプションに応じて)名前はさまざまな方法でマングルされます。また、それらは完全に異なる名前を持ち、その多くは認識できません。異なるコンパイラによって作成されたオブジェクトファイルの互換性を保つには、それらすべての名前に同意する必要があり、決して同意しません。同じコンパイラーの異なるバージョンでさえ常にそれができるわけではありません。


この答えは、バートのものと矛盾するようです。共有ライブラリのみが互換性があるように思えます。Cランタイムライブラリの目に見えない実装固有の機能が相互運用性を妨げる理由を説明していただけますか?また、「実行可能ライブラリまたは実行時リンク可能ライブラリのいずれかを生成するには、Cコンパイラによって発行されたオブジェクトを実行時ライブラリとリンクする必要があります」と言います。静的ライブラリについてはどうですか。
ドーバル

バートが言ったように、ABIを備えたライブラリのみが互換性があります。共有ライブラリ(Unix)はABIの一種ですが、他にもあります。HelloWorld.cを作成し、MSVCとgccでコンパイルし、マップを比較すると、マップの違いがわかります。「ランタイムライブラリ」とは、すべてのC / C ++コンパイルで自動的に参照される必須のサポート関数を意味し、静的または動的にリンクされる場合があります。それらを確認するには、マップまたはCRTソースコードを読んでください。
david.pfx

マップを比較することの意味がわからないので、もう少し具体的になります。実際に、特定のCPUアーキテクチャとOSの組み合わせのすべてのコンパイラに互換性があると仮定ても安全ですか?たとえば、main.cはgccでコンパイルし、mylibrary.cはclangでコンパイルします。どちらもLinux x64を対象としています。合理的に主流のOS(Linux、Mac、Windows)を想定した場合、2つのコンパイラが何であるかに関係なく動作すると想定しても安全ですか?
ドーバル

1
ありそうにないので、clangリンクマップを確認してください。編集を参照してください。
david.pfx 14

17

あなたが探しているのは、ABI(Application Binary Interface)と呼ばれるものです。

C言語ではABIが定義されていないため、その意味では、異なるコンパイラでコンパイルされたCファイルが相互に機能するという保証はありません。

一方、ほとんどのプラットフォームでは、OSはそれとのインターフェース用にABIを定義し、そのOSおよびプロセッサフ​​ァミリをターゲットとするすべてのコンパイラは、非OSコンポーネントとのインターフェース用に同じABIを使用します。そのため、実際には、異なるコンパイラによって作成されたCオブジェクトは相互に連携できます。


それは理にかなっている。共有ライブラリもOSのABIに従うと思いますか?
ドーバル14

3
@Doval 特に共有ライブラリでは、外部から呼び出し可能にする必要があります。
toasted_flakes 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.