다른 컴파일러로 만든 (C) 객체 파일은 이진 호환 가능합니까?


11

C ++ 컴파일러는 서로 호환되지 않는다는 것을 알고 있습니다. 그러나 나는 C에 대해이 주제에서 아무것도 찾을 수 없었습니다. C 표준은 컴파일러가 구현할 수있는 충분한 공간을 남겨둔다는 것을 알고 있지만 대부분의 (모든?) 데이터 유형의 크기와 정렬은 최소한의 보장을 위해 구현 정의 저장입니다. 따라서 두 컴파일러 (또는 동일한 컴파일러의 두 버전)는 수많은 세부 사항에 동의하지 않을 수 있습니다.

다른 컴파일러로 컴파일 된 두 개의 객체 파일이 실제로 올바르게 링크된다는 보장이 없다고 생각하는 것이 맞습니까? 예를 들어, 포인터의 크기는 한 객체 파일에서 32 비트이고 다른 객체 파일에서 64 비트 일 수 있습니다. 그러나 그렇다면 왜 C 라이브러리가 때로는 사전 컴파일 된 형태로 배포됩니까? 내가했던 것과 같은 컴파일러 (예 : gcc) 또는 바이너리 호환성을 보장하기 위해 사용되는 사실상의 표준을 사용할 것이라는 기대가 있습니까? 그리고 외국어 인터페이스를 가진 다른 언어는 어떻게 C 객체 파일과 링크 할 때 올바르게 정렬되도록합니까?


내가 기억할 수있는 한, C 객체 파일은 동일한 플랫폼 용으로 컴파일되는 한 서로 호환 가능해야합니다. 객체 파일은 모듈 내의 각 심볼에 액세스하는 데 사용할 수있는 심볼 테이블이있는로드 가능한 이진 코드가 들어있는 아카이브입니다.
Giorgio

2
libs 호환 가능, 나는 obj가 보장된다고 생각하지 않는다
ratchet freak

@Giorgo "동일한 플랫폼"이란 CPU 아키텍처 또는 CPU 아키텍처 + OS를 의미합니까?
Doval

@ratchetfreak 나는 lib가 대부분 여러 객체 파일의 연결이라는 인상을 받았습니다. 그게 잘못이야?
Doval

객체가 다른 컴파일러에서 호환되지 않을 것으로 기대합니다.
old_timer

답변:


10

일반적인 대답은 아니오입니다. C 언어 컴파일러는 서로 호환되지 않습니다. C 언어 표준은 어떤 종류의 이진 상호 운용성을 정의하지 않으며 대부분의 컴파일러 작성자는 시도조차하지 않습니다.

나는 그것을 자격이 필요합니다. C 컴파일러가 생성 한 객체는 런타임 라이브러리와 연결되어 실행 가능 파일이나 런타임 연결 가능 라이브러리를 생성해야합니다. C 런타임 라이브러리가 제공하는 가시적 기능은 호환 가능해야하지만 구현에 고유하고 상호 운용성을 방지하는 보이지 않는 기능도 있습니다.

이러한 호환성 부족은 동일한 컴파일러의 다른 버전으로 확장됩니다. 일반적으로 이전 버전과 최신 버전의 컴파일러로 컴파일 된 프로그램과 라이브러리는 함께 연결할 수 없으며 MSVC로 컴파일 된 프로그램과 라이브러리는 GCC에서 컴파일 한 것과 연결할 수 없습니다.

구체적이고 유용한 예외가 있습니다. 모든 플랫폼은 동적 연결 ABI (Application Binary Interface) 및 해당 ABI를 준수 할 수있는 모든 언어의 프로그램을 제공합니다. 따라서 일반적으로 MSVC (또는 다른 것)를 사용하여 DLL (Windows에서)을 빌드하고 다른 버전의 MSVC 또는 GCC에 의해 컴파일 된 프로그램에서 또는 그 반대로 호출 할 수 있습니다.

Windows에는 COM 및 .NET 어셈블리라는 두 가지 다른 ABI가 있으며 다양한 언어에 걸쳐 있습니다. 따라서 상호 운용성이 가능하지만 호환되지는 않습니다.


링커 맵을 비교하면 비 호환성의 정도를 쉽게 확인할 수 있습니다. GNU 사용 ld -M, MSVC 사용 link /map. 생성 된 두 파일을 연구하십시오. 두 옵션 모두 printf 및 main과 같이 사용자가 인식 할 수있는 이름을 갖지만 (옵션에 따라) 이름이 여러 방식으로 엉망이 될 수 있습니다. 그들은 또한 완전히 다른 이름을 가질 것입니다. 서로 다른 컴파일러에서 생성 한 객체 파일이 호환 되려면 모든 이름에 동의해야하며 절대 그렇지 않습니다. 동일한 컴파일러의 다른 버전조차도 항상 그렇게 할 수는 없습니다.


이 답변은 Bart 와 모순되는 것으로 보인다 . 공유 라이브러리 만 호환되는 것처럼 들립니다. C 런타임 라이브러리의 보이지 않는 구현 별 기능이 상호 운용성을 방해하는 이유를 설명해 주시겠습니까? 또한 "C 컴파일러가 생성 한 객체는 런타임 라이브러리와 링크되어 실행 파일 또는 런타임 링크 가능 라이브러리를 생성해야합니다"라고 말합니다.
Doval

Bart가 말했듯이 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)를 가정하면 두 컴파일러가 무엇이든 상관없이 작동한다고 가정해도 안전합니까?
Doval

1
가능성이 낮 으면 clang 링크 맵을 확인하십시오. 편집을 참조하십시오.
david.pfx

17

당신이 찾고있는 것은 ABI (Application Binary Interface)입니다.

C 언어는 ABI를 정의하지 않으므로 다른 컴파일러로 컴파일 된 C 파일이 서로 작동한다는 보장은 없습니다.

반면, 대부분의 플랫폼에서 OS는 ABI와 인터페이스하기위한 ABI를 정의하고 OS 및 프로세서 제품군을 대상으로하는 모든 컴파일러는 비 OS 구성 요소와 인터페이스하기 위해 동일한 ABI를 사용합니다. 따라서 실제로 다른 컴파일러에서 만든 C 개체는 서로 작동 할 수 있습니다.


말이 되네요 공유 라이브러리가 OS의 ABI도 따라갑니다.
도발

3
@Doval 특히 공유 라이브러리는 외부 세계에서 호출 할 수 있어야합니다.
toasted_flakes
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.