Apakah file objek (C) dibuat dengan kompiler berbeda yang kompatibel dengan biner?

11

Saya mengerti bahwa kompiler C ++ tidak kompatibel satu sama lain. Namun, saya tidak dapat menemukan apapun tentang topik ini untuk C khususnya. Saya tahu bahwa standar C menyisakan banyak ruang bagi kompiler untuk mengimplementasikan hal-hal yang mereka anggap cocok: misalnya, ukuran dan penyelarasan sebagian besar (semua?) Tipe data ditentukan oleh implementasi, hemat untuk beberapa jaminan minimal. Oleh karena itu, dua kompiler (atau dua versi dari kompiler yang sama) dapat tidak setuju pada banyak detail.

Apakah saya benar dalam berpikir bahwa tidak ada jaminan bahwa dua file objek yang dikompilasi dengan kompiler yang berbeda akan terhubung dengan benar? Misalnya, ukuran pointer bisa 32 bit di satu file objek dan 64 bit di yang lain. Tetapi jika demikian, mengapa perpustakaan C kadang-kadang didistribusikan dalam bentuk yang dikompilasi? Apakah ada harapan bahwa saya akan menggunakan kompiler yang sama seperti yang mereka lakukan (misalnya gcc), atau standar de facto yang digunakan untuk memastikan kompatibilitas biner? Dan bagaimana bahasa lain dengan Antarmuka Bahasa Asing memastikan hal-hal akan berbaris dengan benar ketika menghubungkan dengan file objek C?

Doval
sumber
Sejauh yang saya ingat, file objek C harus kompatibel satu sama lain selama mereka dikompilasi untuk platform yang sama. File objek hanyalah arsip yang berisi kode biner yang dapat dimuat dengan beberapa tabel simbol yang dapat digunakan untuk mengakses setiap simbol di dalam modul.
Giorgio
2
Lib dapat dibuat kompatibel, saya tidak berpikir obj dijamin
ratchet freak
@Giorgo Dengan "platform yang sama", maksud Anda arsitektur CPU atau arsitektur CPU + OS?
Doval
@ scratchetfreak Saya mendapat kesan lib untuk sebagian besar hanya gabungan dari beberapa file objek. Apakah itu salah?
Doval
Saya tidak berharap objek kompatibel di berbagai kompiler.
old_timer

Jawaban:

10

Jawaban umum adalah tidak, kompiler bahasa C tidak kompatibel satu sama lain. Standar bahasa C tidak mendefinisikan interoperabilitas biner apa pun, dan sebagian besar penulis kompiler bahkan tidak mencoba.

Saya harus memenuhi syarat itu. Objek yang dipancarkan oleh kompiler C harus dihubungkan dengan pustaka runtime untuk menghasilkan pustaka yang dapat dieksekusi atau runtime yang dapat ditautkan. Meskipun fungsi yang terlihat yang disediakan oleh pustaka runtime C harus kompatibel, akan ada juga fungsi yang tidak terlihat yang unik untuk implementasi dan mencegah interoperabilitas.

Kurangnya kompatibilitas ini juga meluas ke versi berbeda dari kompiler yang sama. Secara umum, program dan pustaka yang dikompilasi dengan versi kompiler yang lebih lama dan lebih baru tidak dapat dihubungkan bersamaan, dan yang dikompilasi dengan MSVC tidak dapat dihubungkan dengan yang dikompilasi oleh GCC.

Ada pengecualian khusus dan sangat berguna. Setiap platform menyediakan ABI penghubung dinamis (Application Binary Interface) dan program apa pun dalam bahasa apa pun yang dapat sesuai dengan ABI yang kompatibel. Oleh karena itu secara umum dimungkinkan untuk membangun DLL (di Windows) dengan MSVC (atau yang lainnya) dan menyebutnya dari program yang dikompilasi oleh versi MSVC yang berbeda atau oleh GCC dan sebaliknya.

Ada dua ABI lain di Windows: COM dan .NET assemblies, dan mereka menjangkau berbagai bahasa. Jadi interoperabilitas jelas dimungkinkan, tetapi tidak kompatibel.


Tingkat ketidakcocokan dapat dengan mudah dilihat dengan membandingkan peta tautan. Untuk penggunaan GNU ld -M, untuk penggunaan MSVC link /map. Pelajari dua file yang dihasilkan. Keduanya akan memiliki nama-nama di dalamnya yang Anda kenali, seperti printf dan main, meskipun (tergantung pada opsi) nama-nama tersebut kemungkinan akan hancur dalam berbagai cara. Mereka juga akan memiliki nama yang sama sekali berbeda, yang banyak di antaranya tidak akan Anda kenali. Agar file objek yang dihasilkan oleh kompiler berbeda agar kompatibel, mereka harus menyetujui semua nama itu, dan mereka tidak pernah melakukannya. Bahkan versi berbeda dari kompiler yang sama selalu dapat melakukan itu.

david.pfx
sumber
Jawaban ini tampaknya bertentangan dengan jawaban Bart ; sepertinya hanya pustaka bersama yang kompatibel. Bisakah Anda menjelaskan mengapa fungsi implementasi runtime C yang tidak terlihat dan spesifik mencegah interoperabilitas? Anda juga mengatakan "objek yang dipancarkan oleh kompiler C harus dihubungkan dengan pustaka runtime untuk menghasilkan pustaka yang dapat dieksekusi atau runtime yang dapat ditautkan" - bagaimana dengan pustaka statis?
Doval
Seperti yang Bart katakan, hanya perpustakaan dengan ABI yang kompatibel. Pustaka bersama (di Unix) adalah satu jenis ABI, ada yang lain. Tulis HelloWorld.c, kompilasi dengan MSVC dan gcc, bandingkan peta dan Anda akan melihat betapa berbedanya mereka. 'Runtime libraries' berarti fungsi pendukung penting yang secara otomatis dirujuk dalam setiap kompilasi C / C ++, yang mungkin terkait secara statis atau dinamis. Baca peta atau kode sumber CRT untuk melihatnya.
david.pfx
Saya tidak tahu apa artinya membandingkan peta sehingga saya akan sedikit lebih spesifik: apakah aman untuk mengasumsikan dalam prakteknya bahwa semua kompiler untuk arsitektur CPU DAN kombinasi OS yang diberikan kompatibel? Misalnya saya punya main.c, yang saya kompilasi dengan gcc dan mylibrary.c yang saya kompilasi dengan dentang, keduanya menargetkan Linux x64. Dengan asumsi OS yang cukup umum (Linux, Mac, Windows), apakah aman untuk menganggap itu akan berfungsi terlepas dari apa dua kompiler itu?
Doval
1
Sangat tidak mungkin, periksa peta dentang tautan. Lihat edit.
david.pfx
17

Apa yang Anda cari di disebut ABI (Application Binary Interface).

Bahasa C tidak mendefinisikan ABI, jadi dalam hal itu memang tidak ada jaminan bahwa file C yang dikompilasi dengan kompiler yang berbeda akan bekerja satu sama lain.

Di sisi lain, pada kebanyakan platform OS mendefinisikan ABI untuk berinteraksi dengannya dan semua kompiler yang menargetkan keluarga prosesor & OS juga menggunakan ABI yang sama untuk berinteraksi dengan komponen non-OS. Jadi, dalam praktiknya, objek C yang dibuat oleh kompiler yang berbeda dapat bekerja satu sama lain.

Bart van Ingen Schenau
sumber
Itu masuk akal. Saya bawa perpustakaan bersama mengikuti ABI OS juga?
Doval
3
@Doval Khususnya perpustakaan yang dibagikan, mereka harus dapat dipanggil oleh dunia luar.
toasted_flakes