Les fichiers objets (C) sont-ils créés avec différents compilateurs compatibles binaires?

11

Je comprends que les compilateurs C ++ ne sont pas compatibles entre eux. Cependant, je n'ai rien trouvé sur ce sujet pour C en particulier. Je sais que la norme C laisse beaucoup de place aux compilateurs pour implémenter les choses comme bon leur semble: par exemple, la taille et l'alignement de la plupart (tous?) Des types de données sont définis par l'implémentation, à l'exception de quelques garanties minimales. Par conséquent, deux compilateurs (ou deux versions du même compilateur) peuvent être en désaccord sur de nombreux détails.

Ai-je raison de penser qu'il n'y a aucune garantie que deux fichiers objets compilés avec des compilateurs différents seront effectivement liés correctement? Par exemple, la taille des pointeurs peut être de 32 bits dans un fichier objet et de 64 bits dans l'autre. Mais si c'est le cas, pourquoi les bibliothèques C sont-elles parfois distribuées sous forme précompilée? Y a-t-il une attente que j'utiliserai le même compilateur qu'eux (par exemple gcc), ou une norme de facto utilisée pour assurer la compatibilité binaire? Et comment les autres langues avec une interface en langue étrangère garantissent-elles que les choses s'aligneront correctement lors de la liaison avec les fichiers d'objets C?

Doval
la source
Pour autant que je me souvienne, les fichiers d'objets C devraient être compatibles entre eux tant qu'ils sont compilés pour la même plate-forme. Un fichier objet est juste une archive contenant du code binaire chargeable avec une table de symboles qui peut être utilisée pour accéder à chaque symbole à l'intérieur du module.
Giorgio
2
les bibliothèques peuvent être rendues compatibles, je ne pense pas que les obj soient garantis
ratchet freak
@Giorgo Par "même plate-forme", voulez-vous dire architecture CPU ou architecture CPU + OS?
Doval
@ratchetfreak J'avais l'impression qu'une bibliothèque n'est pour la plupart qu'une concaténation de plusieurs fichiers objets. Est-ce faux?
Doval
Je ne m'attendrais pas à ce que les objets soient compatibles entre différents compilateurs.
old_timer

Réponses:

10

La réponse générale est non, les compilateurs en langage C ne sont pas compatibles entre eux. Le standard du langage C ne définit aucun type d'interopérabilité binaire, et la plupart des rédacteurs de compilateurs n'essaient même pas.

Je dois qualifier cela. Les objets émis par un compilateur C doivent être liés aux bibliothèques d'exécution pour produire soit une bibliothèque exécutable soit une bibliothèque exécutable. Bien que les fonctions visibles fournies par la bibliothèque d'exécution C doivent être compatibles, il y aura également des fonctions non visibles qui sont uniques à l'implémentation et empêchent l'interopérabilité.

Ce manque de compatibilité s'étend également aux différentes versions du même compilateur. En général, les programmes et bibliothèques compilés avec des versions plus anciennes et plus récentes d'un compilateur ne peuvent pas être liés ensemble, et ceux compilés avec MSVC ne peuvent pas être liés avec ceux compilés par GCC.

Il existe une exception spécifique et très utile. Chaque plate-forme fournit une liaison dynamique ABI (Application Binary Interface) et tout programme dans n'importe quel langage qui peut se conformer à cette ABI est compatible. Par conséquent, il est généralement possible de créer une DLL (sous Windows) avec MSVC (ou autre chose) et de l'appeler à partir d'un programme compilé par une version différente de MSVC ou par GCC et vice versa.

Il existe deux autres ABI sur Windows: les assemblys COM et .NET, et ils couvrent un large éventail de langues. L'interopérabilité est donc certainement possible, mais compatible, elle ne l'est pas.


Le degré d'incompatibilité peut facilement être vu en comparant les cartes de l'éditeur de liens. Pour une utilisation GNU ld -M, pour une utilisation MSVC link /map. Étudiez les deux fichiers générés. Les deux auront des noms que vous reconnaissez, tels que printf et main, bien que (selon les options) les noms soient susceptibles d'être modifiés de diverses manières. Ils auront également des noms complètement différents, dont beaucoup ne seront pas reconnus. Pour que les fichiers objets produits par différents compilateurs soient compatibles, ils doivent s'accorder sur tous ces noms, et ils ne le font jamais. Même les différentes versions du même compilateur ne peuvent pas toujours le faire.

david.pfx
la source
Cette réponse semble contredire celle de Bart ; il semble que seules les bibliothèques partagées soient compatibles. Pourriez-vous expliquer pourquoi les fonctions non visibles et spécifiques à l'implémentation de la bibliothèque d'exécution C empêchent l'interopérabilité? Vous dites également que "les objets émis par un compilateur C doivent être liés aux bibliothèques d'exécution pour produire un exécutable ou une bibliothèque exécutable" - qu'en est-il des bibliothèques statiques?
Doval
Comme l'a dit Bart, seules les bibliothèques avec un ABI sont compatibles. Les bibliothèques partagées (sous Unix) sont un type d'ABI, il y en a d'autres. Écrivez HelloWorld.c, compilez-le avec MSVC et gcc, comparez les cartes et vous verrez à quel point elles sont différentes. «Bibliothèques d'exécution» signifie les fonctions de support essentielles référencées automatiquement dans chaque compilation C / C ++, qui peuvent être liées statiquement ou dynamiquement. Lisez la carte ou le code source CRT pour les voir.
david.pfx
Je ne sais pas ce que signifie la comparaison des cartes, je serai donc un peu plus précis: est-il sûr de supposer dans la pratique que tous les compilateurs pour une architecture CPU et une combinaison de systèmes d'exploitation donnés sont compatibles? Par exemple, j'ai main.c, que je compile avec gcc et mylibrary.c que je compile avec clang, tous deux ciblant Linux x64. En supposant un OS raisonnablement grand public (Linux, Mac, Windows), est-il sûr de supposer que cela fonctionnerait indépendamment de ce que sont les deux compilateurs?
Doval
1
Très peu probable, consultez la carte des liens de Clang. Voir modifier.
david.pfx
17

Ce que vous recherchez s'appelle ABI (Application Binary Interface).

Le langage C ne définit pas d'ABI, donc dans ce sens il n'y a en effet aucune garantie que les fichiers C compilés avec différents compilateurs fonctionneront les uns avec les autres.

D'un autre côté, sur la plupart des plates-formes, le système d'exploitation définit un ABI pour l'interfaçage avec lui et tous les compilateurs ciblant ce système d'exploitation et cette famille de processeurs utilisent également ce même ABI pour l'interfaçage avec des composants non-OS. Ainsi, dans la pratique, les objets C créés par différents compilateurs peuvent fonctionner ensemble.

Bart van Ingen Schenau
la source
Ça a du sens. Je suppose que les bibliothèques partagées suivent également l'ABI du système d'exploitation?
Doval
3
@Doval Particulièrement les bibliothèques partagées, elles doivent pouvoir être appelées par le monde extérieur.
toasted_flakes