Sind (C) Objektdateien, die mit verschiedenen Compilern erstellt wurden, binär kompatibel?

11

Ich verstehe, dass C ++ - Compiler nicht miteinander kompatibel sind. Allerdings konnte ich zu diesem Thema insbesondere für C nichts finden. Ich weiß, dass der C-Standard den Compilern viel Raum lässt, um Dinge zu implementieren, wie sie es für richtig halten: Beispielsweise ist die Größe und Ausrichtung der meisten (alle?) Datentypen implementierungsdefiniert, abgesehen von einigen minimalen Garantien. Daher können zwei Compiler (oder zwei Versionen desselben Compilers) in zahlreichen Details nicht übereinstimmen.

Habe ich Recht, wenn ich denke, dass es keine Garantie dafür gibt, dass zwei mit verschiedenen Compilern kompilierte Objektdateien tatsächlich richtig verknüpft werden? Beispielsweise könnte die Größe von Zeigern in einer Objektdatei 32 Bit und in der anderen 64 Bit betragen. Aber wenn ja, warum werden C-Bibliotheken manchmal in vorkompilierter Form verteilt? Gibt es eine Erwartung, dass ich denselben Compiler verwenden werde (z. B. gcc), oder einen De-facto- Standard, der verwendet wird, um die Binärkompatibilität sicherzustellen? Und wie stellen andere Sprachen mit einer Fremdsprachenschnittstelle sicher, dass die Dinge beim Verknüpfen mit C-Objektdateien richtig ausgerichtet sind?

Doval
quelle
Soweit ich mich erinnern kann, sollten C-Objektdateien miteinander kompatibel sein, solange sie für dieselbe Plattform kompiliert werden. Eine Objektdatei ist nur ein Archiv, das ladbaren Binärcode mit einer Symboltabelle enthält, mit der auf jedes Symbol im Modul zugegriffen werden kann.
Giorgio
2
libs können kompatibel gemacht werden, ich glaube nicht, dass obj garantiert sein wird
Ratschenfreak
@Giorgo Mit "gleiche Plattform" meinen Sie CPU-Architektur oder CPU-Architektur + Betriebssystem?
Doval
@ratchetfreak Ich hatte den Eindruck, dass eine Bibliothek größtenteils nur eine Verkettung mehrerer Objektdateien ist. Ist das falsch?
Doval
Ich würde nicht erwarten, dass Objekte über verschiedene Compiler hinweg kompatibel sind.
old_timer

Antworten:

10

Die allgemeine Antwort lautet Nein, C-Sprach-Compiler sind nicht miteinander kompatibel. Der C-Sprachstandard definiert keinerlei binäre Interoperabilität, und die meisten Compiler-Autoren versuchen es nicht einmal.

Ich muss das qualifizieren. Die von einem C-Compiler ausgegebenen Objekte müssen mit Laufzeitbibliotheken verknüpft werden, um entweder eine ausführbare oder eine zur Laufzeit verknüpfbare Bibliothek zu erstellen. Obwohl die von der C-Laufzeitbibliothek bereitgestellten sichtbaren Funktionen kompatibel sein sollten, gibt es auch nicht sichtbare Funktionen, die nur für die Implementierung gelten und die Interoperabilität verhindern.

Diese mangelnde Kompatibilität erstreckt sich auch auf verschiedene Versionen desselben Compilers. Im Allgemeinen können Programme und Bibliotheken, die mit älteren und neueren Versionen eines Compilers kompiliert wurden, nicht miteinander verknüpft werden, und Programme, die mit MSVC kompiliert wurden, können nicht mit denen verknüpft werden, die von GCC kompiliert wurden.

Es gibt eine spezifische und sehr nützliche Ausnahme. Jede Plattform bietet eine dynamische Verknüpfung von ABI (Application Binary Interface) und jedes Programm in jeder Sprache, die diesem ABI entsprechen kann, ist kompatibel. Daher ist es im Allgemeinen möglich, eine DLL (unter Windows) mit MSVC (oder etwas anderem) zu erstellen und sie aus einem Programm aufzurufen, das von einer anderen Version von MSVC oder von GCC kompiliert wurde, und umgekehrt.

Unter Windows gibt es zwei weitere ABIs: COM- und .NET-Assemblys, die eine Vielzahl von Sprachen umfassen. Interoperabilität ist also definitiv möglich, aber nicht kompatibel.


Der Grad der Inkompatibilität kann leicht durch Vergleichen der Linker-Maps festgestellt werden. Für die Verwendung mit GNU ld -M, für die Verwendung mit MSVC link /map. Studieren Sie die beiden generierten Dateien. Beide enthalten Namen, die Sie erkennen, z. B. printf und main, obwohl die Namen (abhängig von den Optionen) wahrscheinlich auf verschiedene Weise entstellt werden. Sie haben auch völlig andere Namen, von denen Sie viele nicht erkennen. Damit Objektdateien, die von verschiedenen Compilern erstellt wurden, kompatibel sind, müssen sie sich auf all diese Namen einigen, und das tun sie niemals. Das können nicht einmal verschiedene Versionen desselben Compilers.

david.pfx
quelle
Diese Antwort scheint Bart zu widersprechen ; Es hört sich so an, als wären nur gemeinsam genutzte Bibliotheken kompatibel. Können Sie erklären, warum die nicht sichtbaren, implementierungsspezifischen Funktionen der C-Laufzeitbibliothek die Interoperabilität verhindern? Sie sagen auch, dass "die von einem C-Compiler ausgegebenen Objekte mit Laufzeitbibliotheken verknüpft werden müssen, um entweder eine ausführbare oder eine zur Laufzeit verknüpfbare Bibliothek zu erstellen" - was ist mit statischen Bibliotheken?
Doval
Wie Bart sagte, sind nur Bibliotheken mit einem ABI kompatibel. Freigegebene Bibliotheken (unter Unix) sind eine Art von ABI, es gibt andere. Schreiben Sie HelloWorld.c, kompilieren Sie es mit MSVC und gcc, vergleichen Sie die Karten und Sie werden sehen, wie unterschiedlich sie sind. 'Laufzeitbibliotheken' bezeichnet die wesentlichen Unterstützungsfunktionen, auf die in jeder C / C ++ - Kompilierung automatisch verwiesen wird und die statisch oder dynamisch verknüpft sein können. Lesen Sie die Karte oder den CRT-Quellcode, um sie anzuzeigen.
david.pfx
Ich weiß nicht, was das Vergleichen der Maps bedeutet, daher werde ich etwas genauer darauf eingehen: Kann man in der Praxis davon ausgehen , dass alle Compiler für eine bestimmte Kombination aus CPU-Architektur und Betriebssystem kompatibel sind? ZB habe ich main.c, die ich mit gcc kompiliere, und mylibrary.c, die ich mit clang kompiliere, beide für Linux x64. Ist es unter der Annahme eines vernünftigen Mainstream-Betriebssystems (Linux, Mac, Windows) sicher anzunehmen, dass dies unabhängig von den beiden Compilern funktionieren würde?
Doval
1
Sehr unwahrscheinlich, überprüfen Sie die Clang Link Map. Siehe Bearbeiten.
david.pfx
17

Was Sie suchen, wird als ABI (Application Binary Interface) bezeichnet.

Die C-Sprache definiert kein ABI. In diesem Sinne gibt es in der Tat keine Garantie dafür, dass C-Dateien, die mit verschiedenen Compilern kompiliert wurden, miteinander funktionieren.

Andererseits definiert das Betriebssystem auf den meisten Plattformen einen ABI für die Schnittstelle mit ihm, und alle Compiler, die auf diese Betriebssystem- und Prozessorfamilie abzielen, verwenden denselben ABI auch für die Schnittstelle mit Nicht-Betriebssystemkomponenten. In der Praxis können C-Objekte, die von verschiedenen Compilern erstellt wurden, miteinander arbeiten.

Bart van Ingen Schenau
quelle
Das macht Sinn. Ich nehme an, dass gemeinsam genutzte Bibliotheken auch dem ABI des Betriebssystems folgen.
Doval
3
@Doval Insbesondere gemeinsam genutzte Bibliotheken müssen von der Außenwelt aufgerufen werden können.
Toasted_flakes