Các tệp đối tượng (C) được tạo với các trình biên dịch khác nhau có tương thích nhị phân không?


11

Tôi hiểu rằng trình biên dịch C ++ không tương thích với nhau. Tuy nhiên, tôi không thể tìm thấy bất cứ điều gì về chủ đề này cho C nói riêng. Tôi biết rằng tiêu chuẩn C còn rất nhiều chỗ cho trình biên dịch triển khai mọi thứ theo cách chúng thấy phù hợp: ví dụ: kích thước và sự liên kết của hầu hết các loại dữ liệu (tất cả?) Là tiết kiệm được xác định theo thực thi cho một số đảm bảo tối thiểu. Do đó, hai trình biên dịch (hoặc hai phiên bản của cùng một trình biên dịch) có thể không đồng ý về nhiều chi tiết.

Tôi có đúng không khi nghĩ rằng không có gì đảm bảo rằng hai tệp đối tượng được biên dịch với các trình biên dịch khác nhau sẽ thực sự liên kết đúng không? Ví dụ, kích thước của con trỏ có thể là 32 bit trong một tệp đối tượng và 64 bit trong tệp kia. Nhưng nếu đó là như vậy, tại sao các thư viện C đôi khi được phân phối ở dạng tiền biên dịch? Có một kỳ vọng rằng tôi sẽ sử dụng cùng một trình biên dịch mà họ đã làm (ví dụ gcc), hoặc một số tiêu chuẩn thực tế đang được sử dụng để đảm bảo khả năng tương thích nhị phân? Và làm thế nào để các ngôn ngữ khác có Giao diện Ngoại ngữ đảm bảo mọi thứ sẽ xếp hàng đúng khi liên kết với các tệp đối tượng C?


Theo như tôi có thể nhớ, các tệp đối tượng C phải tương thích với nhau miễn là chúng được biên dịch cho cùng một nền tảng. Một tệp đối tượng chỉ là một kho lưu trữ chứa mã nhị phân có thể tải với một số bảng ký hiệu có thể được sử dụng để truy cập từng ký hiệu bên trong mô-đun.
Giorgio

2
lib có thể được làm cho tương thích, tôi không nghĩ obj được đảm bảo
ratchet freak

@Giorgo Theo "cùng một nền tảng", ý bạn là kiến ​​trúc CPU hay kiến ​​trúc CPU + HĐH?
Doval

@ratchetfreak Tôi đã có ấn tượng rằng một lib là phần lớn chỉ là sự kết hợp của nhiều tệp đối tượng. Là sai đó?
Doval

Tôi không mong đợi các đối tượng sẽ tương thích trên các trình biên dịch khác nhau.
old_timer

Câu trả lời:


10

Câu trả lời chung là không, trình biên dịch ngôn ngữ C không tương thích với nhau. Tiêu chuẩn ngôn ngữ C không định nghĩa bất kỳ loại khả năng tương tác nhị phân nào và hầu hết các nhà văn biên dịch thậm chí không thử.

Tôi cần phải đủ điều kiện đó. Các đối tượng được phát ra bởi trình biên dịch C phải được liên kết với các thư viện thời gian chạy để tạo thư viện thực thi hoặc thư viện có thể liên kết được. Mặc dù các chức năng hiển thị được cung cấp bởi thư viện thời gian chạy C phải tương thích, nhưng cũng sẽ có các chức năng không nhìn thấy được duy nhất để thực hiện và ngăn chặn khả năng tương tác.

Sự thiếu tương thích này cũng mở rộng sang các phiên bản khác nhau của cùng một trình biên dịch. Nói chung, các chương trình và thư viện được biên dịch với các phiên bản cũ hơn và mới hơn của trình biên dịch không thể được liên kết với nhau và những chương trình được biên dịch bằng MSVC không thể được liên kết với các phiên bản được biên dịch bởi GCC.

Có một ngoại lệ cụ thể và rất hữu ích. Mọi nền tảng đều cung cấp một ABI liên kết động (Giao diện nhị phân ứng dụng) và bất kỳ chương trình nào trong bất kỳ ngôn ngữ nào có thể phù hợp với ABI đó đều tương thích. Do đó, nói chung có thể xây dựng một DLL (trên Windows) bằng MSVC (hoặc một cái gì đó khác) và gọi nó từ một chương trình được biên dịch bởi một phiên bản khác của MSVC hoặc bởi GCC và ngược lại.

Có hai ABI khác trên Windows: COM và .NET, và chúng trải rộng trên nhiều ngôn ngữ. Vì vậy, khả năng tương tác là hoàn toàn có thể, nhưng tương thích thì không.


Mức độ không tương thích có thể dễ dàng được nhìn thấy bằng cách so sánh các bản đồ liên kết. Để sử dụng GNU ld -M, sử dụng MSVC link /map. Nghiên cứu hai tập tin được tạo ra. Cả hai sẽ có tên trong đó mà bạn nhận ra, chẳng hạn như printf và main, mặc dù (tùy thuộc vào tùy chọn), các tên có khả năng được đọc sai theo nhiều cách khác nhau. Họ cũng sẽ có những cái tên hoàn toàn khác nhau, nhiều trong số đó bạn sẽ không nhận ra. Để các tệp đối tượng được tạo bởi các trình biên dịch khác nhau tương thích, chúng phải đồng ý với tất cả các tên đó và chúng không bao giờ thực hiện. Thậm chí không có các phiên bản khác nhau của cùng một trình biên dịch có thể làm điều đó.


Câu trả lời này dường như mâu thuẫn với Bart ; có vẻ như chỉ có các thư viện chia sẻ là tương thích. Bạn có thể giải thích tại sao các chức năng không thể thực hiện, cụ thể của thư viện thời gian chạy C ngăn cản khả năng tương tác? Bạn cũng nói "các đối tượng được phát ra bởi trình biên dịch C phải được liên kết với các thư viện thời gian chạy để tạo thư viện thực thi hoặc thư viện liên kết thời gian chạy" - còn thư viện tĩnh thì sao?
Doval

Như Bart đã nói, chỉ các thư viện có ABI là tương thích. Thư viện dùng chung (trên Unix) là một loại ABI, có những loại khác. Viết HelloWorld.c, biên dịch nó với MSVC và gcc, so sánh các bản đồ và bạn sẽ thấy chúng khác nhau như thế nào. 'Thư viện thời gian chạy' có nghĩa là các hàm hỗ trợ thiết yếu được tự động tham chiếu trong mọi trình biên dịch C / C ++, có thể được liên kết tĩnh hoặc động. Đọc bản đồ hoặc mã nguồn CRT để xem chúng.
david.pfx

Tôi không biết việc so sánh các bản đồ có nghĩa là gì nên tôi sẽ nói rõ hơn một chút: có an toàn không khi cho rằng trong thực tế tất cả các trình biên dịch cho một kiến ​​trúc CPU và kết hợp HĐH nhất định đều tương thích? Ví dụ: tôi có main.c, mà tôi biên dịch bằng gcc và myl Library.c mà tôi biên dịch bằng clang, cả hai đều nhắm mục tiêu Linux x64. Giả sử một hệ điều hành hợp lý chính thống (Linux, Mac, Windows), có an toàn không khi cho rằng nó sẽ hoạt động bất kể hai trình biên dịch là gì?
Doval

1
Rất khó xảy ra, kiểm tra bản đồ liên kết clang. Xem chỉnh sửa.
david.pfx

17

Những gì bạn đang tìm kiếm được gọi là ABI (Application Binary Interface).

Ngôn ngữ C không định nghĩa ABI, vì vậy theo nghĩa đó, thực sự không có gì đảm bảo rằng các tệp C được biên dịch với các trình biên dịch khác nhau sẽ hoạt động với nhau.

Mặt khác, trên hầu hết các nền tảng, HĐH xác định ABI để giao tiếp với nó và tất cả các trình biên dịch nhắm mục tiêu họ OS và bộ xử lý cũng sử dụng cùng ABI đó để giao tiếp với các thành phần không phải HĐH. Vì vậy, trong thực tế, các đối tượng C được tạo bởi các trình biên dịch khác nhau có thể làm việc với nhau.


Điều đó có ý nghĩa. Tôi cũng lấy nó thư viện chia sẻ theo ABI của hệ điều hành?
Doval

3
@Doval Đặc biệt là các thư viện được chia sẻ, chúng cần được thế giới bên ngoài gọi được.
to nướng_flakes
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.