Soll ich mit / MD oder / MT kompilieren?

126

In Visual Studio gibt es die Kompilierungsflags / MD und / MT, mit denen Sie auswählen können, welche Art von C-Laufzeitbibliothek Sie möchten.

Ich verstehe den Unterschied in der Implementierung, bin mir aber immer noch nicht sicher, welchen ich verwenden soll. Was sind die Vor- und Nachteile?

Ein Vorteil von / MD, den ich gehört habe, ist, dass dies jemandem ermöglicht, die Laufzeit zu aktualisieren (z. B. ein Sicherheitsproblem zu beheben), und meine App von diesem Update profitiert. Obwohl mir das fast wie eine Nicht-Funktion erscheint: Ich möchte nicht, dass Leute meine Laufzeit ändern, ohne dass ich gegen die neue Version testen kann!

Einige Dinge, auf die ich neugierig bin:

  • Wie würde sich dies auf die Bauzeiten auswirken? (vermutlich / MT ist etwas langsamer?)
  • Was sind die anderen Implikationen?
  • Welches benutzen die meisten Leute?
Andy
quelle
1
Weitere Informationen und Vorschläge finden Sie unter: stackoverflow.com/questions/787216
Weidenrinde

Antworten:

85

Durch dynamische Verknüpfung mit / MD,

  • Sie sind Systemaktualisierungen ausgesetzt (für gut oder schlecht),
  • Ihre ausführbare Datei kann kleiner sein (da die Bibliothek nicht darin eingebettet ist)
  • Ich glaube, dass zumindest das Codesegment einer DLL von allen Prozessen gemeinsam genutzt wird, die sie aktiv verwenden (wodurch der Gesamtverbrauch an RAM reduziert wird).

Ich habe auch festgestellt, dass in der Praxis / MT in der Hauptanwendung bei der Arbeit mit statisch verknüpften Nur-Binär-Bibliotheken von Drittanbietern, die mit unterschiedlichen Laufzeitoptionen erstellt wurden, häufig Konflikte verursacht als / MD (weil Sie Es treten Probleme auf, wenn die C-Laufzeit mehrmals statisch verknüpft ist, insbesondere wenn es sich um unterschiedliche Versionen handelt.

Herr Fooz
quelle
10
Das Systemaktualisierungsbit wird durch SxS etwas reduziert. Die EXE kann deklarieren, welche CRT-Version sie will (will, bekommt nicht - Sicherheitsupdates können dies außer Kraft setzen)
MSalters
1
Bedeutet dies, dass wenn ich mit MD kompiliere und mein Programm von einer DLL abhängig ist, das Programm fehlschlägt, wenn es auf einem Computer ausgeführt wird, auf dem die Abhängigkeits-DLL nicht vorhanden ist?
Gerrytan
5
@gerrytan: Ja, Sie müssen sicherstellen, dass die entsprechenden verwendeten DLLs auf allen Computern vorhanden sind, auf denen die Software ausgeführt werden soll. Typische Lösungen hierfür sind, dass der Benutzer das entsprechende weiterverteilbare MSVC-Paket installiert oder ein Installationsprogramm verwendet, das die gesamte Arbeit erledigt.
Herr Fooz
@ Royi Ich bin mir nicht sicher, aber ich denke /MT, dass es zur Laufzeit etwas schneller sein wird, da Ihre App nicht jedes Mal nach der Implementierung der Laufzeitfunktion suchen muss. Ich bin kein Experte auf diesem Niveau, aber ich bin mir ziemlich sicher, dass die meisten Betriebssysteme werden die Laufzeitimplementierungen zwischenspeichern, sodass Ihre App die zwischengespeicherte Version verwendet, sodass der Unterschied nicht so weit ist. HINWEIS: Ich habe erwähnt, dass ich nicht sicher bin. Nehmen Sie diesen Kommentar also nicht als Argument.
Ahmed Kamal
34

Wenn Sie DLLs verwenden, sollten Sie sich für die dynamisch verknüpfte CRT (/ MD) entscheiden.

Wenn Sie die dynamische CRT für Ihre EXE-Datei und alle DLLs verwenden, teilen sich alle eine einzige Implementierung der CRT. Dies bedeutet, dass alle einen einzigen CRT-Heap gemeinsam nutzen und der in einer EXE / DLL zugewiesene Speicher freigegeben werden kann Ein weiterer.

Wenn Sie die statische CRT für Ihre EXE-Datei und alle DLLs verwenden, erhalten alle eine separate Kopie der CRT. Dies bedeutet, dass alle ihren eigenen CRT-Heap verwenden, sodass der Speicher in demselben Modul freigegeben werden muss, in dem sie sich befinden wurde zugeteilt. Sie leiden auch unter aufgeblähtem Code (mehrere Kopien der CRT) und übermäßigem Laufzeit-Overhead (jeder Heap weist dem Betriebssystem Speicher zu, um den Status zu verfolgen, und der Overhead kann spürbar sein).

JoeG
quelle
20

Ich glaube, der Standard für Projekte, die über Visual Studio erstellt wurden, ist / MD.

Wenn Sie / MT verwenden, hängt Ihre ausführbare Datei nicht davon ab, ob auf dem Zielsystem eine DLL vorhanden ist. Wenn Sie dies in ein Installationsprogramm einbinden, ist dies wahrscheinlich kein Problem, und Sie können in beide Richtungen vorgehen.

Ich benutze / MT selbst, damit ich das ganze DLL-Chaos ignorieren kann.

PS Wie Herr Fooz betont , ist es wichtig, konsequent zu sein. Wenn Sie mit anderen Bibliotheken verknüpfen, müssen Sie dieselbe Option verwenden, die sie verwenden. Wenn Sie eine DLL eines Drittanbieters verwenden, ist es fast sicher, dass Sie die DLL-Version der Laufzeitbibliothek verwenden müssen.

Mark Ransom
quelle
14

Ich verlinke lieber statisch mit / MT.

Auch wenn Sie mit / MD eine kleinere ausführbare Datei erhalten, müssen Sie dennoch eine Reihe von DLLs ausliefern, um sicherzustellen, dass der Benutzer die richtige Version zum Ausführen Ihres Programms erhält. Und am Ende wird Ihr Installer GRÖSSER sein als beim Verknüpfen mit / MT.

Was noch schlimmer ist, wenn Sie Ihre Laufzeitbibliotheken in das Windows-Verzeichnis stellen, wird der Benutzer früher oder später eine neue Anwendung mit verschiedenen Bibliotheken installieren und mit etwas Pech Ihre Anwendung beschädigen.

Adrian Grigore
quelle
5
Sehr schlechte Idee, "Ihre Laufzeitbibliotheken in das Windows-Verzeichnis zu stellen". Sie können andere dumme Anwendungen brechen, die dasselbe getan haben, bevor Sie es getan haben. Verwenden Sie SxS und lassen Sie das Installationsprogramm damit umgehen oder bleiben Sie bei / MT.
MSalters
1
Ich stimme voll und ganz zu, dass es eine schlechte Idee ist. Einige Leute tun es jedoch, deshalb habe ich beschrieben, warum dies keine gute Idee ist.
Adrian Grigore
@AdrianGrigore Warum würde eine neue Anwendung mit verschiedenen Bibliotheken eine Unterbrechung in Ihrer Anwendung verursachen? Wenn Sie die / MD-Verknüpfung verwenden, laden Sie einfach die neuen Versionen der Bibliotheken, oder?
rturrado
4
@ rturrado: nicht ganz. Wenn Sie andere Anwendungen zusätzlich zu Ihren installieren, werden Ihre DLLs möglicherweise mit älteren Versionen überschrieben. Die neueren Versionen wären weg. Dies ist allgemein bekannt als "dll hell", siehe en.wikipedia.org/wiki/DLL_Hell
Adrian Grigore
1
Microsoft hat WinSxS in Visual Studio 2010 aufgegeben - Laufzeitbibliotheken werden jetzt entweder privat oder in system32 bereitgestellt ( msdn.microsoft.com/en-us/library/vstudio/dd293574.aspx ).
BCran
8

Das Problem, auf das Sie mit / MD stoßen, besteht darin, dass sich die Zielversion der CRT möglicherweise nicht auf dem Computer Ihres Benutzers befindet (insbesondere, wenn Sie die neueste Version von Visual Studio verwenden und der Benutzer ein älteres Betriebssystem hat).

In diesem Fall müssen Sie herausfinden, wie Sie die richtige Version auf ihren Computer bekommen.

i_am_jorf
quelle
7

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

/ MT Definiert _MT so, dass Multithread-spezifische Versionen der Laufzeitroutinen aus den Standard-Header-Dateien (.h) ausgewählt werden. Diese Option bewirkt auch, dass der Compiler den Bibliotheksnamen LIBCMT.lib in die OBJ-Datei einfügt, sodass der Linker LIBCMT.lib verwendet, um externe Symbole aufzulösen. Zum Erstellen von Multithread-Programmen ist entweder / MT oder / MD (oder deren Debug-Äquivalente / MTd oder / MDd) erforderlich.

/ MD Definiert _MT und _DLL so, dass sowohl Multithread- als auch DLL-spezifische Versionen der Laufzeitroutinen aus den Standard-H-Dateien ausgewählt werden. Diese Option bewirkt auch, dass der Compiler den Bibliotheksnamen MSVCRT.lib in die OBJ-Datei einfügt.

Mit dieser Option kompilierte Anwendungen sind statisch mit MSVCRT.lib verknüpft. Diese Bibliothek bietet eine Codeebene, mit der der Linker externe Referenzen auflösen kann. Der eigentliche Arbeitscode ist in MSVCR71.DLL enthalten, das zur Laufzeit für mit MSVCRT.lib verknüpfte Anwendungen verfügbar sein muss.

Wenn / MD mit definiertem _STATIC_CPPLIB (/ D_STATIC_CPPLIB) verwendet wird, wird die Anwendung mit der statischen Multithread-Standard-C ++ - Bibliothek (libcpmt.lib) anstelle der dynamischen Version (msvcprt.lib) verknüpft, während weiterhin eine dynamische Verbindung mit der Haupt-CRT über hergestellt wird msvcrt.lib.

Wenn ich es also richtig interpretiere, verknüpft / MT statisch und / MD dynamisch.

Lothar
quelle
Die Frage war "Welches soll ich verwenden?", Dies ist keine Antwort.
Leonard Inkret
1

Wenn Sie eine ausführbare Datei erstellen, die andere DLLs oder Bibliotheken als die Option / MD verwendet, wird dies bevorzugt, da auf diese Weise alle Komponenten dieselbe Bibliothek gemeinsam nutzen. Natürlich sollte diese Option für alle beteiligten Module übereinstimmen, dh dll / lib / exe.

Wenn Ihre ausführbare Datei keine lib oder dll verwendet, kann niemand sie aufrufen. Der Unterschied ist jetzt nicht zu groß, da der Aspekt des Teilens nicht ins Spiel kommt.

Vielleicht können Sie die Anwendung mit / MT starten, da es keinen zwingenden Grund dafür gibt, aber wenn es Zeit ist, eine Bibliothek oder DLL hinzuzufügen, können Sie sie mit der der Bibliothek / DLL in / MD ändern, was einfach ist.

zar
quelle