Devo compilare con / MD o / MT?


126

In Visual Studio sono disponibili i flag di compilazione / MD e / MT che consentono di scegliere il tipo di libreria di runtime C desiderata.

Capisco la differenza nell'implementazione, ma non sono ancora sicuro di quale utilizzare. Quali sono i pro / contro?

Un vantaggio di / MD che ho sentito è che ciò consente a qualcuno di aggiornare il runtime, (come forse correggere un problema di sicurezza) e la mia app trarrà vantaggio da questo aggiornamento. Anche se per me, questo sembra quasi una non funzionalità: non voglio che le persone cambino il mio tempo di esecuzione senza permettermi di testare con la nuova versione!

Alcune cose di cui sono curioso:

  • In che modo ciò influirebbe sui tempi di costruzione? (presumibilmente / MT è un po 'più lento?)
  • Quali sono le altre implicazioni?
  • Quale usa la maggior parte delle persone?

1
Maggiori informazioni e suggerimenti si possono trovare in: stackoverflow.com/questions/787216
Weidenrinde

Risposte:


85

Collegando dinamicamente con / MD,

  • sei esposto agli aggiornamenti di sistema (nel bene o nel male),
  • l'eseguibile può essere più piccolo (poiché non contiene la libreria incorporata) e
  • Credo che almeno il segmento di codice di una DLL sia condiviso tra tutti i processi che lo stanno attivamente utilizzando (riducendo la quantità totale di RAM consumata).

Ho anche scoperto che in pratica, quando si lavora con librerie solo binarie di terze parti collegate staticamente che sono state costruite con diverse opzioni di runtime, / MT nell'applicazione principale tende a causare conflitti molto più spesso di / MD (perché tu incontrerò problemi se il runtime C è staticamente collegato più volte, specialmente se si tratta di versioni diverse).


10
Il bit di aggiornamento del sistema è in qualche modo ridotto da SxS. Il EXE arriva a dichiarare quale versione CRT vuole (vuole, non ottiene - gli aggiornamenti di sicurezza potrebbero
prevalere su

1
Questo significa che se compilo usando MD e il mio programma dipende da qualche DLL, il programma fallirà se è in esecuzione su un computer in cui la DLL di dipendenza è inesistente?
Gerrytan,

5
@gerrytan: Sì, dovrai assicurarti che le DLL appropriate utilizzate siano presenti su tutti i computer che desiderano eseguire il software. Soluzioni tipiche a questo sono che l'utente installi il pacchetto ridistribuibile MSVC appropriato o usi un programma di installazione che fa tutto il lavoro.
Fooz,

@Royi Non ne sono sicuro ma penso che /MTsarà leggermente più veloce in fase di esecuzione poiché la tua app non ha bisogno di cercare l'implementazione della funzione di runtime ogni volta, non sono un esperto a questo livello ma sono quasi sicuro che la maggior parte di I sistemi operativi memorizzeranno nella cache le implementazioni di runtime in modo che l'app utilizzi la versione cache, quindi la differenza non sarà così lontana, NOTA che ho detto che non sono sicuro, quindi non prendere questo commento come argomento.
Ahmed Kamal,

34

Se si utilizzano DLL, è consigliabile utilizzare il CRT (/ MD) collegato dinamicamente.

Se usi il CRT dinamico per il tuo .exe e tutti i .dll, tutti condivideranno un'unica implementazione del CRT, il che significa che condivideranno tutti un singolo heap CRT e la memoria allocata in un .exe / .dll può essere liberata in un altro.

Se usi il CRT statico per il tuo .exe e tutti i .dll riceveranno tutti una copia separata del CRT, il che significa che useranno tutti il ​​loro heap CRT quindi la memoria deve essere liberata nello stesso modulo in cui è stato assegnato. Soffrirai anche di bloat di codice (più copie del CRT) e sovraccarico di runtime in eccesso (ogni heap alloca memoria dal sistema operativo per tenere traccia del suo stato e l'overhead può essere evidente).


20

Credo che il valore predefinito per i progetti creati tramite Visual Studio sia / MD.

Se usi / MT, il tuo eseguibile non dipenderà dalla presenza di una DLL sul sistema di destinazione. Se lo stai racchiudendo in un programma di installazione, probabilmente non sarà un problema e puoi andare in entrambi i modi.

Uso me stesso / MT, in modo da poter ignorare l'intero pasticcio DLL.

PS Come sottolinea Mr. Fooz , è fondamentale essere coerenti. Se stai collegando con altre librerie, devi usare la stessa opzione che fanno. Se si utilizza una DLL di terze parti, è quasi certo che sarà necessario utilizzare la versione DLL della libreria di runtime.


14

Preferisco collegarmi staticamente con / MT.

Anche se ottieni un eseguibile più piccolo con / MD, devi comunque spedire un sacco di DLL per assicurarti che l'utente ottenga la versione giusta per eseguire il tuo programma. E alla fine il tuo programma di installazione sarà più GRANDE rispetto al collegamento con / MT.

Quel che è peggio, se scegli di mettere le tue librerie di runtime nella directory di Windows, prima o poi l'utente installerà una nuova applicazione con librerie diverse e, con sfortuna, romperà la tua applicazione.


5
Pessima idea di "mettere le librerie di runtime nella directory di Windows". Puoi interrompere altre applicazioni stupide che hanno fatto lo stesso prima di te. Usa SxS e lascia che sia l'installatore a gestirlo, oppure mantieni il controllo con / MT.
MSalters,

1
Sono pienamente d'accordo che sia una cattiva idea. Alcune persone lo fanno, quindi stavo descrivendo perché questa non è una buona idea.
Adrian Grigore,

@AdrianGrigore perché una nuova applicazione con librerie diverse potrebbe causare un'interruzione dell'applicazione? Se usi il collegamento / MD, inizieresti a caricare le nuove versioni delle librerie, giusto?
Rturrado,

4
@rturrado: non del tutto. L'installazione di altre applicazioni sopra le tue potrebbe sovrascrivere le tue dll con versioni precedenti. Le versioni più recenti sarebbero sparite. Questo è comunemente noto come "inferno dll", vedi en.wikipedia.org/wiki/DLL_Hell
Adrian Grigore,

1
Microsoft ha rinunciato a WinSxS in Visual Studio 2010 - le librerie di runtime sono ora distribuite privatamente o in system32 ( msdn.microsoft.com/en-us/library/vstudio/dd293574.aspx ).
BCran,

8

Il problema con cui ti imbatterai in / MD è che la versione di destinazione di CRT potrebbe non essere sul tuo computer degli utenti (specialmente se stai usando l'ultima versione di Visual Studio e l'utente ha un sistema operativo precedente).

In tal caso, devi capire come ottenere la versione giusta sulla loro macchina.


7

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

/ MT Definisce _MT in modo che le versioni specifiche del multithread delle routine di runtime siano selezionate dai file di intestazione standard (.h). Questa opzione fa inoltre in modo che il compilatore inserisca il nome della libreria LIBCMT.lib nel file .obj in modo che il linker utilizzi LIBCMT.lib per risolvere i simboli esterni. Per creare programmi multithread è necessario / MT o / MD (o i loro equivalenti di debug / MTd o / MDd).

/ MD Definisce _MT e _DLL in modo che sia le versioni specifiche del multithread sia quelle della DLL delle routine di runtime siano selezionate dai file .h standard. Questa opzione fa inoltre in modo che il compilatore inserisca il nome della libreria MSVCRT.lib nel file .obj.

Le applicazioni compilate con questa opzione sono staticamente collegate a MSVCRT.lib. Questa libreria fornisce un livello di codice che consente al linker di risolvere riferimenti esterni. Il codice di lavoro effettivo è contenuto in MSVCR71.DLL, che deve essere disponibile in fase di esecuzione per le applicazioni collegate a MSVCRT.lib.

Quando / MD viene utilizzato con _STATIC_CPPLIB definito (/ D_STATIC_CPPLIB) causerà il collegamento dell'applicazione con la libreria C ++ standard multithread statica (libcpmt.lib) invece della versione dinamica (msvcprt.lib) mentre si collega dinamicamente al CRT principale tramite msvcrt.lib.

Quindi, se lo sto interpretando correttamente, allora / MT collega staticamente e / MD collega dinamicamente.


La domanda era "quale dovrei usare?", Questa non è una risposta.
Leonard Inkret,

1

Se stai costruendo un eseguibile che utilizza altre opzioni dlls o libs / / MD è preferito perché in questo modo tutti i componenti condivideranno la stessa libreria. Naturalmente questa opzione dovrebbe corrispondere per tutti i moduli coinvolti, ad esempio dll / lib / exe.

Se il tuo eseguibile non usa alcuna lib o dll della sua chiamata di chiunque. La differenza non è troppo adesso perché l'aspetto di condivisione non è in gioco.

Quindi forse puoi avviare l'applicazione con / MT poiché non vi è alcun motivo convincente altrimenti, ma quando è il momento di aggiungere una lib o una dll, puoi cambiarla in / MD con quella della lib / dll che è facile.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.