I file oggetto (C) creati con compilatori diversi sono binari compatibili?


11

Comprendo che i compilatori C ++ non sono compatibili tra loro. Tuttavia, non sono riuscito a trovare nulla su questo argomento per C in particolare. So che lo standard C lascia molto spazio ai compilatori per implementare le cose nel modo che ritengono opportuno: ad esempio, la dimensione e l'allineamento della maggior parte (tutti?) Dei tipi di dati è un salvataggio definito dall'implementazione per alcune garanzie minime. Pertanto, due compilatori (o due versioni dello stesso compilatore) possono non essere d'accordo su numerosi dettagli.

Sono corretto nel pensare che non vi sia alcuna garanzia che due file oggetto compilati con compilatori diversi si colleghino correttamente? Ad esempio, la dimensione dei puntatori potrebbe essere 32 bit in un file oggetto e 64 bit nell'altro. Ma se è così, perché a volte le librerie C sono distribuite in forma precompilata? C'è un'aspettativa che userò lo stesso compilatore hanno fatto (ad esempio gcc), o qualche de facto essendo utilizzata per garantire la compatibilità binaria? E in che modo altre lingue con un'interfaccia in lingua straniera assicurano che le cose si allineino correttamente quando si collegano con i file oggetto C?


Per quanto posso ricordare, i file oggetto C dovrebbero essere compatibili tra loro fintanto che sono compilati per la stessa piattaforma. Un file oggetto è solo un archivio contenente codice binario caricabile con una tabella di simboli che può essere utilizzata per accedere a ciascun simbolo all'interno del modulo.
Giorgio,

2
le librerie possono essere rese compatibili, non credo che gli obj siano garantiti
maniaco del cricchetto

@Giorgo Per "stessa piattaforma", intendi architettura CPU o architettura CPU + SO?
Doval,

@ratchetfreak Ho avuto l'impressione che una lib sia per la maggior parte solo una concatenazione di più file oggetto. È sbagliato?
Doval,

Non mi aspetto che gli oggetti siano compatibili tra diversi compilatori.
old_timer

Risposte:


10

La risposta generale è no, i compilatori in linguaggio C non sono compatibili tra loro. Lo standard del linguaggio C non definisce alcun tipo di interoperabilità binaria e la maggior parte degli autori di compilatori non ci prova nemmeno.

Devo qualificarlo. Gli oggetti emessi da un compilatore C devono essere collegati con le librerie di runtime per produrre una libreria eseguibile o collegabile in runtime. Sebbene le funzioni visibili fornite dalla libreria di runtime C debbano essere compatibili, ci saranno anche funzioni non visibili che sono uniche per l'implementazione e impediscono l'interoperabilità.

Questa mancanza di compatibilità si estende anche a diverse versioni dello stesso compilatore. In generale, i programmi e le librerie compilati con le versioni precedenti e più recenti di un compilatore non possono essere collegati tra loro e quelli compilati con MSVC non possono essere collegati con quelli compilati da GCC.

C'è un'eccezione specifica e molto utile. Ogni piattaforma fornisce un collegamento dinamico ABI (Application Binary Interface) e qualsiasi programma in qualsiasi lingua che sia conforme a tale ABI è compatibile. Pertanto è generalmente possibile creare una DLL (su Windows) con MSVC (o qualcos'altro) e chiamarla da un programma compilato da una versione diversa di MSVC o da GCC e viceversa.

Esistono altre due ABI su Windows: assembly COM e .NET e abbracciano una vasta gamma di lingue. Quindi l'interoperabilità è sicuramente possibile, ma non lo sono compatibili.


Il grado di incompatibilità può essere facilmente visto confrontando le mappe dei linker. Per uso GNU ld -M, per uso MSVC link /map. Studia i due file generati. Entrambi avranno nomi che riconoscerai, come printf e main, sebbene (a seconda delle opzioni) i nomi possano essere alterati in vari modi. Avranno anche nomi completamente diversi, molti dei quali non riconoscerai. Affinché i file oggetto prodotti da diversi compilatori siano compatibili, devono concordare su tutti quei nomi e non lo fanno mai. Nemmeno versioni diverse dello stesso compilatore possono sempre farlo.


Questa risposta sembra contraddire quella di Bart ; sembra che solo le librerie condivise siano compatibili. Potresti spiegare perché le funzioni non visibili e specifiche dell'implementazione della libreria C runtime impediscono l'interoperabilità? Dici anche "gli oggetti emessi da un compilatore C devono essere collegati con le librerie di runtime per produrre una libreria eseguibile o una runtime collegabile" - che dire delle librerie statiche?
Doval,

Come ha detto Bart, solo le librerie con un ABI sono compatibili. Le librerie condivise (su Unix) sono un tipo di ABI, ce ne sono altre. Scrivi HelloWorld.c, compilarlo con MSVC e gcc, confrontare le mappe e vedrai quanto sono diverse. Per "librerie di runtime" si intendono le funzioni di supporto essenziali a cui fa automaticamente riferimento ogni compilazione C / C ++, che può essere collegata staticamente o dinamicamente. Leggi la mappa o il codice sorgente CRT per vederli.
david.pfx,

Non so cosa significhi confrontare le mappe, quindi sarò un po 'più specifico: è sicuro supporre in pratica che tutti i compilatori per una determinata architettura CPU e combinazione di SO siano compatibili? Ad esempio, ho main.c, che compilo con gcc e mylibrary.c, che compilo con clang, entrambi destinati a Linux x64. Supponendo un sistema operativo ragionevolmente mainstream (Linux, Mac, Windows), è sicuro supporre che funzionerebbe indipendentemente da cosa siano i due compilatori?
Doval,

1
Molto improbabile, controlla la mappa dei collegamenti clang. Vedi modifica.
david.pfx,

17

Quello che cerchi è chiamato ABI (Application Binary Interface).

Il linguaggio C non definisce un ABI, quindi in tal senso non esiste alcuna garanzia che i file C compilati con compilatori diversi funzionino tra loro.

D'altra parte, sulla maggior parte delle piattaforme il sistema operativo definisce un ABI per l'interfacciamento con esso e tutti i compilatori destinati a tale sistema operativo e famiglia di processori usano anche lo stesso ABI per l'interfacciamento con componenti non OS. Quindi, in pratica, gli oggetti C creati da diversi compilatori possono lavorare tra loro.


Ha senso. Prendo che le librerie condivise seguano anche l'ABI del sistema operativo?
Doval,

3
@Doval Librerie specialmente condivise, devono essere richiamabili dal mondo esterno.
toasted_flakes
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.