ฉันควรคอมไพล์ด้วย / MD หรือ / MT?


127

ใน Visual Studio มีแฟล็กคอมไพล์ / MD และ / MT ซึ่งให้คุณเลือกประเภทของไลบรารีรันไทม์ C ที่คุณต้องการ

ฉันเข้าใจความแตกต่างในการใช้งาน แต่ฉันยังไม่แน่ใจว่าจะใช้อันไหนดี ข้อดี / ข้อเสียคืออะไร?

ข้อดีอย่างหนึ่งของ / MD ที่ฉันเคยได้ยินมาคือสิ่งนี้ช่วยให้ผู้อื่นอัปเดตรันไทม์ได้ (เช่นอาจจะแก้ไขปัญหาด้านความปลอดภัย) และแอปของฉันจะได้รับประโยชน์จากการอัปเดตนี้ แม้ว่าสำหรับฉันแล้วสิ่งนี้ดูเหมือนจะไม่ใช่ฟีเจอร์: ฉันไม่ต้องการให้คนอื่นเปลี่ยนรันไทม์โดยไม่อนุญาตให้ฉันทดสอบกับเวอร์ชันใหม่!

บางสิ่งที่ฉันอยากรู้เกี่ยวกับ:

  • สิ่งนี้จะส่งผลต่อเวลาในการสร้างอย่างไร (น่าจะ / MT ช้ากว่านิดหน่อย?)
  • ความหมายอื่น ๆ คืออะไร?
  • คนส่วนใหญ่ใช้อันไหน?

1
สามารถดูข้อมูลและข้อเสนอแนะเพิ่มเติมได้ใน: stackoverflow.com/questions/787216
Weidenrinde

คำตอบ:


87

โดยการเชื่อมโยงแบบไดนามิกกับ / MD

  • คุณกำลังเผชิญกับการอัปเดตระบบ (ดีหรือไม่ดี)
  • ไฟล์ปฏิบัติการของคุณอาจมีขนาดเล็กลง (เนื่องจากไม่มีไลบรารีฝังอยู่) และ
  • ฉันเชื่อว่าอย่างน้อยที่สุดส่วนรหัสของ DLL จะถูกแชร์ระหว่างกระบวนการทั้งหมดที่ใช้งานอยู่ (ลดจำนวน RAM ทั้งหมดที่ใช้ไป)

ฉันยังพบว่าในทางปฏิบัติเมื่อทำงานกับไลบรารีไบนารีของบุคคลที่สามที่เชื่อมโยงแบบคงที่ซึ่งสร้างขึ้นด้วยตัวเลือกรันไทม์ที่แตกต่างกัน / MT ในแอปพลิเคชันหลักมีแนวโน้มที่จะทำให้เกิดความขัดแย้งบ่อยกว่า / MD (เพราะคุณ จะประสบปัญหาหากรันไทม์ C ถูกเชื่อมโยงแบบคงที่หลายครั้งโดยเฉพาะอย่างยิ่งหากเป็นเวอร์ชันที่แตกต่างกัน)


11
บิตการอัปเดตระบบจะลดลงเล็กน้อยโดย SxS EXE ได้รับการประกาศว่า CRT เวอร์ชันใดที่ต้องการ (ต้องการไม่ได้รับ - การอัปเดตความปลอดภัยอาจลบล้างสิ่งนี้)
MSalters

1
นี่หมายความว่าถ้าฉันคอมไพล์โดยใช้ MD และโปรแกรมของฉันขึ้นอยู่กับ dll บางตัวโปรแกรมจะล้มเหลวถ้ามันทำงานบนคอมพิวเตอร์ที่ไม่มี dll ที่ขึ้นต่อกัน?
gerrytan

5
@gerrytan: ใช่คุณจะต้องตรวจสอบให้แน่ใจว่ามีการใช้ DLL ที่เหมาะสมในคอมพิวเตอร์ทุกเครื่องที่ต้องการเรียกใช้ซอฟต์แวร์ วิธีแก้ปัญหาโดยทั่วไปคือให้ผู้ใช้ติดตั้งแพคเกจที่แจกจ่ายต่อ MSVC ที่เหมาะสมหรือใช้โปรแกรมติดตั้งที่ทำงานทั้งหมด
Mr Fooz

@Royi ฉันไม่แน่ใจ แต่ฉันคิดว่า/MTรันไทม์จะเร็วขึ้นเล็กน้อยเนื่องจากแอพของคุณไม่จำเป็นต้องค้นหาการใช้งานฟังก์ชันรันไทม์ทุกครั้งฉันไม่ใช่ผู้เชี่ยวชาญในระดับนี้ แต่ฉันค่อนข้างมั่นใจว่าส่วนใหญ่ ระบบปฏิบัติการจะแคชการใช้งานรันไทม์ดังนั้นแอปของคุณจะใช้เวอร์ชันแคชดังนั้นความแตกต่างจะไม่ไกลขนาดนั้นโปรดทราบว่าฉันพูดถึงว่าฉันไม่แน่ใจดังนั้นอย่าใช้ความคิดเห็นนี้เป็นข้อโต้แย้ง
Ahmed Kamal

34

หากคุณใช้ DLL คุณควรไปที่ CRT (/ MD) ที่เชื่อมโยงแบบไดนามิก

หากคุณใช้ CRT แบบไดนามิกสำหรับ. exe และ. dll ทั้งหมดของคุณพวกเขาทั้งหมดจะแบ่งปันการใช้งาน CRT เพียงครั้งเดียวซึ่งหมายความว่าพวกเขาทั้งหมดจะแชร์ฮีป CRT เดียวและหน่วยความจำที่จัดสรรใน. exe / .dll หนึ่งตัวสามารถเป็นอิสระได้ใน อื่น

หากคุณใช้ CRT แบบคงที่สำหรับ. exe และ. dll ทั้งหมดของคุณพวกเขาทั้งหมดจะได้รับสำเนา CRT แยกกันซึ่งหมายความว่าพวกเขาทั้งหมดจะใช้ฮีป CRT ของตัวเองดังนั้นหน่วยความจำจะต้องเป็นอิสระในโมดูลเดียวกันกับที่มัน ได้รับการจัดสรร นอกจากนี้คุณจะต้องทนทุกข์ทรมานจากการขยายตัวของโค้ด (สำเนา CRT หลายชุด) และค่าใช้จ่ายรันไทม์ที่มากเกินไป (แต่ละฮีปจะจัดสรรหน่วยความจำจากระบบปฏิบัติการเพื่อติดตามสถานะและค่าใช้จ่ายที่สามารถสังเกตเห็นได้)


20

ฉันเชื่อว่าค่าเริ่มต้นสำหรับโครงการที่สร้างผ่าน Visual Studio คือ / MD

หากคุณใช้ / MT ไฟล์ปฏิบัติการของคุณจะไม่ขึ้นอยู่กับ DLL ที่มีอยู่ในระบบเป้าหมาย หากคุณกำลังรวมสิ่งนี้ไว้ในโปรแกรมติดตั้งอาจจะไม่มีปัญหาและคุณสามารถไปทางใดทางหนึ่งได้

ฉันใช้ / MT ด้วยตัวเองเพื่อที่ฉันจะได้เพิกเฉยต่อความยุ่งเหยิงของ DLL ทั้งหมด

ป.ล. ตามที่คุณ Foozชี้ให้เห็นสิ่งสำคัญคือต้องมีความสม่ำเสมอ หากคุณกำลังเชื่อมโยงกับไลบรารีอื่น ๆ คุณต้องใช้ตัวเลือกเดียวกับที่ทำ หากคุณใช้ DLL ของบุคคลที่สามเกือบจะแน่นอนว่าคุณจะต้องใช้ไลบรารีรันไทม์เวอร์ชัน DLL


14

ฉันชอบที่จะเชื่อมโยงแบบคงที่กับ / MT

แม้ว่าคุณจะได้รับไฟล์ปฏิบัติการที่มีขนาดเล็กลงด้วย / MD แต่คุณยังต้องจัดส่ง DLL จำนวนมากเพื่อให้แน่ใจว่าผู้ใช้ได้รับเวอร์ชันที่เหมาะสมสำหรับการรันโปรแกรมของคุณ และในท้ายที่สุดโปรแกรมติดตั้งของคุณจะใหญ่กว่าเมื่อเชื่อมโยงกับ / MT

ยิ่งไปกว่านั้นถ้าคุณเลือกที่จะใส่ไลบรารีรันไทม์ของคุณไว้ในไดเร็กทอรี windows ไม่ช้าก็เร็วผู้ใช้จะติดตั้งแอปพลิเคชันใหม่ที่มีไลบรารีที่แตกต่างกันและด้วยความโชคร้ายอาจทำให้แอปพลิเคชันของคุณเสียหาย


5
ความคิดที่แย่มากที่จะ "ใส่ไลบรารีรันไทม์ของคุณไว้ในไดเรกทอรี windows" คุณสามารถทำลายแอปพลิเคชันโง่ ๆ อื่น ๆ ที่ทำแบบเดียวกันก่อนหน้านี้ได้ ใช้ SxS แล้วปล่อยให้โปรแกรมติดตั้งจัดการหรือติดกับ / MT
MSalters

1
ฉันยอมรับอย่างเต็มที่ว่ามันเป็นความคิดที่ไม่ดี บางคนก็ทำเช่นนั้นดังนั้นฉันจึงอธิบายว่าเหตุใดจึงไม่ใช่ความคิดที่ดี
Adrian Grigore

@AdrianGrigore เหตุใดแอปพลิเคชันใหม่ที่มีไลบรารีต่างกันจึงทำให้แอปพลิเคชันของคุณหยุดทำงาน หากคุณใช้การเชื่อมโยง / MD คุณจะเริ่มโหลดไลบรารีเวอร์ชันใหม่ใช่ไหม
rturrado

4
@rturrado: ไม่มาก การติดตั้งแอปพลิเคชั่นอื่น ๆ ไว้ด้านบนของคุณอาจเขียนทับ dlls ของคุณด้วยเวอร์ชันเก่ากว่า เวอร์ชันที่ใหม่กว่าจะหายไป สิ่งนี้เรียกกันทั่วไปว่า "dll hell" ดูที่en.wikipedia.org/wiki/DLL_Hell
Adrian Grigore

1
Microsoft เลิกใช้ WinSxS ใน Visual Studio 2010 - ขณะนี้ไลบรารีรันไทม์ถูกปรับใช้แบบส่วนตัวหรือใน system32 ( msdn.microsoft.com/en-us/library/vstudio/dd293574.aspx )
BCran

8

ปัญหาที่คุณจะพบกับ / MD คือเวอร์ชันเป้าหมายของ CRT อาจไม่อยู่ในเครื่องผู้ใช้ของคุณ (โดยเฉพาะอย่างยิ่งหากคุณใช้ Visual Studio เวอร์ชันล่าสุดและผู้ใช้มีระบบปฏิบัติการรุ่นเก่า)

ในกรณีนี้คุณต้องหาวิธีรับรุ่นที่ถูกต้องลงในเครื่องของพวกเขา


7

จากhttp://msdn.microsoft.com/en-us/library/2kzt1wy3(VS.71).aspx :

/ MT กำหนด _MT เพื่อให้มีการเลือกรูทีนรันไทม์เวอร์ชันเฉพาะแบบมัลติเธรดจากไฟล์ส่วนหัวมาตรฐาน (.h) ตัวเลือกนี้ยังทำให้คอมไพเลอร์วางชื่อไลบรารี LIBCMT.lib ลงในไฟล์. obj เพื่อให้ตัวเชื่อมโยงใช้ LIBCMT.lib เพื่อแก้ไขสัญลักษณ์ภายนอก จำเป็นต้องใช้ / MT หรือ / MD (หรือสิ่งที่เทียบเท่าการดีบัก / MTd หรือ / MDd) เพื่อสร้างโปรแกรมแบบมัลติเธรด

/ MD กำหนด _MT และ _DLL เพื่อให้ทั้งเวอร์ชันมัลติเธรดและเวอร์ชันเฉพาะ DLL ของรูทีนรันไทม์ถูกเลือกจากไฟล์. h มาตรฐาน ตัวเลือกนี้ยังทำให้คอมไพลเลอร์วางชื่อไลบรารี MSVCRT.lib ลงในไฟล์. obj

แอปพลิเคชันที่คอมไพล์ด้วยอ็อพชันนี้จะเชื่อมโยงกับ MSVCRT.lib แบบคงที่ ไลบรารีนี้จัดเตรียมเลเยอร์ของโค้ดที่อนุญาตให้ตัวเชื่อมโยงแก้ไขการอ้างอิงภายนอก รหัสการทำงานจริงมีอยู่ใน MSVCR71.DLL ซึ่งต้องพร้อมใช้งานในขณะรันกับแอปพลิเคชันที่เชื่อมโยงกับ MSVCRT.lib

เมื่อ / MD ถูกใช้กับ _STATIC_CPPLIB ที่กำหนดไว้ (/ D_STATIC_CPPLIB) จะทำให้แอปพลิเคชันเชื่อมโยงกับไลบรารี C ++ มาตรฐานแบบมัลติเธรดแบบสแตติก (libcpmt.lib) แทนเวอร์ชันไดนามิก (msvcprt.lib) ในขณะที่ยังคงลิงก์ไปยัง CRT หลักแบบไดนามิกผ่าน msvcrt.lib

ดังนั้นหากฉันตีความอย่างถูกต้องแล้ว/ MT จะเชื่อมโยงแบบคงที่และลิงก์/ MDแบบไดนามิก


คำถามคือ "ฉันควรใช้อันไหนดี" นี่ไม่ใช่คำตอบ
Leonard Inkret

2

หากคุณกำลังสร้างไฟล์ปฏิบัติการที่ใช้ตัวเลือก dll หรือ libs อื่นที่ไม่ใช่ / MD เป็นที่ต้องการเพราะวิธีนี้คอมโพเนนต์ทั้งหมดจะแชร์ไลบรารีเดียวกัน แน่นอนว่าตัวเลือกนี้ควรตรงกับโมดูลทั้งหมดที่เกี่ยวข้องเช่น dll / lib / exe

หากไฟล์ปฏิบัติการของคุณไม่ได้ใช้ lib หรือ dll ใด ๆ มากกว่าการเรียกของใคร ๆ ตอนนี้ความแตกต่างยังไม่มากนักเพราะด้านการแบ่งปันยังไม่เข้าเล่น

ดังนั้นคุณอาจเริ่มแอปพลิเคชันด้วย / MT ได้เนื่องจากไม่มีเหตุผลที่น่าสนใจเป็นอย่างอื่น แต่เมื่อถึงเวลาเพิ่ม lib หรือ dll คุณสามารถเปลี่ยนเป็น / MD ด้วย lib / dll ซึ่งเป็นเรื่องง่าย

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