ไฟล์วัตถุ (C) ถูกสร้างด้วยคอมไพเลอร์ที่เข้ากันได้กับไบนารีต่างกันหรือไม่?


11

ฉันเข้าใจว่าคอมไพเลอร์ C ++ ไม่สามารถทำงานร่วมกันได้ อย่างไรก็ตามฉันไม่พบสิ่งใดในหัวข้อนี้สำหรับ C โดยเฉพาะ ฉันรู้ว่ามาตรฐาน C ออกจากห้องมากมายสำหรับคอมไพเลอร์ที่จะใช้สิ่งต่าง ๆ แต่พวกเขาเห็นว่าเหมาะสม: ตัวอย่างเช่นขนาดและการจัดแนวของชนิดข้อมูลส่วนใหญ่ (ทั้งหมด?) คือการบันทึกที่ใช้งาน ดังนั้นคอมไพเลอร์สองตัว (หรือคอมไพเลอร์เดียวกันสองเวอร์ชั่น) อาจไม่เห็นด้วยกับรายละเอียดมากมาย

ฉันถูกต้องโดยคิดว่าไม่มีการรับประกันว่าไฟล์ออบเจ็กต์สองไฟล์ที่คอมไพล์ด้วยคอมไพเลอร์ที่ต่างกันจะเชื่อมโยงอย่างถูกต้องจริงหรือ ตัวอย่างเช่นขนาดของพอยน์เตอร์อาจเป็น 32 บิตในหนึ่งอ็อบเจ็กต์ไฟล์และ 64 บิตในอีกอัน แต่ถ้าเป็นเช่นนั้นเหตุใดบางครั้ง C ไลบรารีจึงกระจายในรูปแบบที่คอมไพล์แล้ว? มีความคาดหวังหรือไม่ว่าฉันจะใช้คอมไพเลอร์แบบเดียวกับที่พวกเขาทำ (เช่น gcc) หรือมาตรฐานตามความเป็นจริงบางอย่างที่ใช้ในการรับรองความเข้ากันได้ของไบนารี และภาษาอื่น ๆ ที่มีส่วนต่อประสานกับภาษาต่างประเทศช่วยให้แน่ใจได้อย่างไรว่าสิ่งต่าง ๆ จะเข้าแถวอย่างถูกต้องเมื่อเชื่อมโยงกับไฟล์วัตถุ C?


เท่าที่ฉันจำได้ไฟล์อ็อบเจ็กต์ C ควรทำงานร่วมกันได้ตราบใดที่คอมไพล์แล้วสำหรับแพลตฟอร์มเดียวกัน อ็อบเจ็กต์ไฟล์เป็นไฟล์เก็บถาวรที่มีโค้ดไบนารีที่โหลดได้พร้อมกับตารางสัญลักษณ์บางตัวที่สามารถใช้เพื่อเข้าถึงแต่ละสัญลักษณ์ภายในโมดูล
Giorgio

2
libs สามารถทำให้เข้ากันได้ฉันไม่คิดว่า obj รับประกันว่าจะเป็น
วงล้อประหลาด

@Giorgo โดย "แพลตฟอร์มเดียวกัน" คุณหมายถึงสถาปัตยกรรม CPU หรือสถาปัตยกรรม CPU + OS หรือไม่
Doval

@ ratchetfreak ฉันอยู่ภายใต้การแสดงผล lib เป็นส่วนใหญ่เพียงแค่การเชื่อมต่อของหลายวัตถุไฟล์ มันผิดหรือเปล่า?
Doval

ฉันไม่คาดหวังว่าวัตถุจะเข้ากันได้กับคอมไพเลอร์ที่แตกต่างกัน
old_timer

คำตอบ:


10

คำตอบทั่วไปคือไม่คอมไพเลอร์ภาษา C ไม่สามารถทำงานร่วมกันได้ มาตรฐานภาษา C ไม่ได้กำหนดความสามารถในการทำงานร่วมกันของไบนารีประเภทใดก็ได้และผู้เขียนคอมไพเลอร์ส่วนใหญ่ก็ไม่ได้ลอง

ฉันต้องมีคุณสมบัติที่ วัตถุที่ปล่อยออกมาโดยคอมไพเลอร์ C จะต้องเชื่อมโยงกับไลบรารีรันไทม์เพื่อสร้างไลบรารีที่รันได้หรือไลบรารีที่ลิงก์ได้แบบรันไทม์ แม้ว่าฟังก์ชั่นที่มองเห็นได้จาก C runtime library ควรเข้ากันได้ แต่ก็จะมีฟังก์ชั่นที่ไม่สามารถมองเห็นได้ซึ่งมีลักษณะเฉพาะในการนำไปใช้และป้องกันการทำงานร่วมกัน

การขาดความเข้ากันได้นี้ยังรวมไปถึงเวอร์ชั่นต่าง ๆ ของคอมไพเลอร์เดียวกัน โดยทั่วไปโปรแกรมและไลบรารีที่คอมไพล์ด้วยคอมไพเลอร์เวอร์ชั่นเก่าและใหม่กว่านั้นไม่สามารถเชื่อมโยงเข้าด้วยกันและคอมไพล์ด้วย MSVC ไม่สามารถเชื่อมโยงกับคอมไพล์ที่รวบรวมโดย GCC

มีข้อยกเว้นเฉพาะและมีประโยชน์มาก ทุกแพลตฟอร์มให้การเชื่อมโยง ABI แบบไดนามิก (Application Binary Interface) และโปรแกรมใด ๆ ในภาษาใด ๆ ที่สามารถสอดคล้องกับ ABI ที่เข้ากันได้ ดังนั้นจึงเป็นไปได้ที่จะสร้าง DLL (บน Windows) ด้วย MSVC (หรืออย่างอื่น) และเรียกมันจากโปรแกรมที่คอมไพล์โดย MSVC รุ่นอื่นหรือโดย GCC และในทางกลับกัน

มี ABI อื่น ๆ สองตัวบน Windows: แอสเซมบลี COM และ. NET และพวกเขาครอบคลุมภาษาที่หลากหลาย ดังนั้นการทำงานร่วมกันจึงเป็นไปได้อย่างแน่นอน แต่ก็ไม่สามารถใช้งานร่วมกันได้


ระดับของความไม่ลงรอยกันสามารถมองเห็นได้ง่ายโดยการเปรียบเทียบแผนที่ลิงเกอร์ สำหรับการใช้งาน GNU สำหรับการใช้งานld -M MSVC link /mapศึกษาทั้งสองไฟล์ที่สร้างขึ้น ทั้งสองจะมีชื่ออยู่ในชื่อที่คุณจำได้เช่น printf และ main แม้ว่า (ขึ้นอยู่กับตัวเลือก) ชื่อเหล่านี้มีแนวโน้มที่จะมีหลายรูปแบบ พวกเขาจะมีชื่อที่แตกต่างอย่างสิ้นเชิงโดยที่หลายคนไม่รู้จัก เพื่อให้ไฟล์วัตถุที่ผลิตโดยคอมไพเลอร์ต่างกันเข้ากันได้พวกเขาต้องยอมรับชื่อเหล่านั้นทั้งหมดและพวกเขาไม่เคยทำ คอมไพเลอร์รุ่นเดียวกันไม่ต่างกันก็สามารถทำได้


คำตอบนี้ดูเหมือนจะขัดแย้งกับBart's ; ดูเหมือนว่าเฉพาะไลบรารีที่แชร์เท่านั้นที่เข้ากันได้ คุณช่วยอธิบายได้ไหมว่าทำไมฟังก์ชั่นเฉพาะสำหรับการนำไปใช้งานที่ไม่สามารถมองเห็นได้ของ C runtime library ป้องกันการทำงานร่วมกัน? นอกจากนี้คุณยังพูดว่า "วัตถุที่ปล่อยออกมาโดยคอมไพเลอร์ C ต้องเชื่อมโยงกับไลบรารีรันไทม์เพื่อสร้างไลบรารีที่รันได้หรือไลบรารีที่ลิงก์ได้แบบรันไทม์" - ห้องสมุดแบบคงที่คืออะไร?
Doval

ดังที่ Bart กล่าวว่ามีเพียงห้องสมุดที่มี ABI เท่านั้นที่เข้ากันได้ ไลบรารีที่ใช้ร่วมกัน (บน Unix) เป็นประเภทหนึ่งของ ABI และอื่น ๆ เขียน HelloWorld.c รวบรวมด้วย MSVC และ gcc เปรียบเทียบแผนที่และคุณจะเห็นว่าแตกต่างกันอย่างไร 'ห้องสมุดรันไทม์' หมายถึงฟังก์ชั่นการสนับสนุนที่จำเป็นซึ่งอ้างอิงโดยอัตโนมัติในคอมไพล์ C / C ++ ทุกอันซึ่งอาจเชื่อมโยงแบบสแตติกหรือแบบไดนามิก อ่านแผนที่หรือซอร์สโค้ด CRT เพื่อดู
david.pfx

ฉันไม่รู้ว่าการเปรียบเทียบแผนที่หมายถึงอะไรดังนั้นฉันจะเจาะจงมากกว่านี้เล็กน้อย: ปลอดภัยหรือไม่ที่จะสมมติว่าในทางปฏิบัติแล้วว่าคอมไพเลอร์ทั้งหมดสำหรับสถาปัตยกรรม CPU ที่กำหนดและการรวมกันของ OS นั้นเข้ากันได้หรือไม่ เช่นฉันมี main.c ซึ่งฉันรวบรวมด้วย gcc และ mylibrary.c ซึ่งฉันรวบรวมด้วยเสียงดังกราวทั้งกำหนดเป้าหมาย Linux x64 สมมติว่าระบบปฏิบัติการหลักที่สมเหตุสมผล (Linux, Mac, Windows) มีความปลอดภัยหรือไม่ที่จะสมมติว่ามันจะทำงานได้ไม่ว่าคอมไพเลอร์ทั้งสองนั้นคืออะไร?
Doval

1
ไม่น่าเป็นไปได้อย่างมากให้ตรวจสอบแผนผังการเชื่อมโยงเสียงดังกราว ดูการแก้ไข
david.pfx

17

สิ่งที่คุณกำลังมองหาเรียกว่า ABI (Application Binary Interface)

ภาษา C ไม่ได้กำหนด ABI ดังนั้นในกรณีนี้ไม่มีการรับประกันว่าไฟล์ C ที่คอมไพล์ด้วยคอมไพเลอร์ต่าง ๆ จะทำงานร่วมกันได้

ในทางกลับกันบนแพลตฟอร์มส่วนใหญ่ระบบปฏิบัติการจะกำหนด ABI สำหรับการเชื่อมต่อกับมันและคอมไพเลอร์ทั้งหมดที่กำหนดเป้าหมายว่าตระกูล OS และโปรเซสเซอร์นั้นยังใช้ ABI เดียวกันนั้นสำหรับการเชื่อมต่อกับส่วนประกอบที่ไม่ใช่ระบบปฏิบัติการ ดังนั้นในทางปฏิบัติวัตถุ C ที่สร้างโดยคอมไพเลอร์ต่างกันสามารถทำงานร่วมกันได้


นั่นทำให้รู้สึก ฉันจะใช้ไลบรารีร่วมกันติดตาม ABI ของระบบปฏิบัติการด้วยหรือไม่
Doval

3
@Doval โดยเฉพาะอย่างยิ่งห้องสมุดสาธารณะพวกเขาจำเป็นต้องเรียกใช้จากโลกภายนอก
toasted_flakes
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.