Dois-je compiler avec / MD ou / MT?

126

Dans Visual Studio, il existe les indicateurs de compilation / MD et / MT qui vous permettent de choisir le type de bibliothèque d'exécution C que vous souhaitez.

Je comprends la différence de mise en œuvre, mais je ne sais toujours pas laquelle utiliser. Quels sont les avantages / inconvénients?

Un avantage de / MD que j'ai entendu, est que cela permet à quelqu'un de mettre à jour le runtime (comme peut-être corriger un problème de sécurité) et mon application bénéficiera de cette mise à jour. Bien que pour moi, cela semble presque être une non-fonctionnalité: je ne veux pas que les gens changent mon environnement d'exécution sans me permettre de tester la nouvelle version!

Certaines choses qui m'intéressent:

  • Comment cela affecterait-il les temps de construction? (probablement / MT est un peu plus lent?)
  • Quelles sont les autres implications?
  • Lequel la plupart des gens utilisent-ils?
Andy
la source
1
Plus d'informations et de suggestions peuvent être trouvées sur: stackoverflow.com/questions/787216
Weidenrinde

Réponses:

85

En liant dynamiquement avec / MD,

  • vous êtes exposé aux mises à jour du système (pour le meilleur ou pour le pire),
  • votre exécutable peut être plus petit (car il ne contient pas la bibliothèque intégrée), et
  • Je crois qu'au moins le segment de code d'une DLL est partagé entre tous les processus qui l'utilisent activement (ce qui réduit la quantité totale de RAM consommée).

J'ai également constaté que dans la pratique, lorsque vous travaillez avec des bibliothèques binaires tierces uniquement liées statiquement qui ont été créées avec différentes options d'exécution, / MT dans l'application principale a tendance à provoquer des conflits beaucoup plus souvent que / MD (car vous 'va rencontrer des problèmes si le runtime C est lié statiquement plusieurs fois, surtout s'il s'agit de versions différentes).

Monsieur Fooz
la source
10
Le bit de mise à jour du système est quelque peu réduit par SxS. L'EXE peut déclarer la version CRT qu'il veut (veut, pas obtient - les mises à jour de sécurité pourraient annuler cela)
MSalters
1
Cela signifie-t-il que si je compile en utilisant MD et que mon programme dépend de certaines dll, le programme échouera s'il s'exécute sur un ordinateur où la dll de dépendance est inexistante?
gerrytan
5
@gerrytan: Oui, vous devrez vous assurer que les DLL appropriées utilisées sont présentes sur tous les ordinateurs qui souhaitent exécuter le logiciel. Les solutions typiques à ce problème consistent à demander à l'utilisateur d'installer le package redistribuable MSVC approprié ou à utiliser un programme d'installation qui effectue tout le travail.
Mr Fooz
@Royi Je ne suis pas sûr, mais je pense que ce /MTsera légèrement plus rapide à l'exécution puisque votre application n'a pas besoin de rechercher l'implémentation de la fonction d'exécution à chaque fois, je ne suis pas un expert à ce niveau mais je suis presque sûr que la plupart des Les systèmes d'exploitation mettront en cache les implémentations d'exécution afin que votre application utilise la version mise en cache, donc la différence ne sera pas aussi loin, NOTEZ que j'ai mentionné que je ne suis pas sûr, alors ne prenez pas ce commentaire comme argument.
Ahmed Kamal
34

Si vous utilisez des DLL, vous devriez opter pour le CRT (/ MD) lié dynamiquement.

Si vous utilisez le CRT dynamique pour votre .exe et tous les .dll, ils partageront tous une seule implémentation du CRT - ce qui signifie qu'ils partageront tous un seul tas CRT et que la mémoire allouée dans un .exe / .dll peut être libérée dans un autre.

Si vous utilisez le CRT statique pour votre .exe et tous les .dll, ils recevront tous une copie distincte du CRT - ce qui signifie qu'ils utiliseront tous leur propre tas CRT, donc la mémoire doit être libérée dans le même module dans lequel elle a été attribué. Vous souffrirez également d'une surcharge de code (plusieurs copies du CRT) et d'une surcharge d'exécution excessive (chaque tas alloue de la mémoire du système d'exploitation pour garder une trace de son état, et la surcharge peut être perceptible).

JoeG
la source
20

Je crois que la valeur par défaut pour les projets créés via Visual Studio est / MD.

Si vous utilisez / MT, votre exécutable ne dépendra pas de la présence d'une DLL sur le système cible. Si vous enveloppez cela dans un programme d'installation, ce ne sera probablement pas un problème et vous pouvez aller dans les deux sens.

J'utilise / MT moi-même, de sorte que je puisse ignorer tout le désordre DLL.

PS Comme le souligne M. Fooz , il est essentiel d'être cohérent. Si vous créez un lien avec d'autres bibliothèques, vous devez utiliser la même option qu'eux. Si vous utilisez une DLL tierce, il est presque certain que vous devrez utiliser la version DLL de la bibliothèque d'exécution.

Mark Ransom
la source
14

Je préfère établir un lien statique avec / MT.

Même si vous obtenez un exécutable plus petit avec / MD, vous devez toujours envoyer un tas de DLL pour vous assurer que l'utilisateur obtient la bonne version pour exécuter votre programme. Et à la fin, votre installateur sera PLUS GRAND que lors de la liaison avec / MT.

Pire encore, si vous choisissez de mettre vos bibliothèques d'exécution dans le répertoire Windows, tôt ou tard, l'utilisateur va installer une nouvelle application avec différentes bibliothèques et, avec un peu de malchance, casser votre application.

Adrian Grigore
la source
5
Très mauvaise idée de "mettre vos bibliothèques d'exécution dans le répertoire windows". Vous pouvez casser d'autres applications stupides qui ont fait la même chose avant vous. Utilisez SxS et laissez l'installateur le gérer, ou restez avec / MT.
MSalters
1
Je suis entièrement d'accord que c'est une mauvaise idée. Certaines personnes le font cependant, alors je décrivais pourquoi ce n'est pas une bonne idée.
Adrian Grigore
@AdrianGrigore pourquoi une nouvelle application avec différentes bibliothèques provoquerait-elle une rupture dans votre application? Si vous utilisez la liaison / MD, vous commenceriez simplement à charger les nouvelles versions des bibliothèques, n'est-ce pas?
rturrado le
4
@rturrado: pas tout à fait. L'installation d'autres applications par-dessus les vôtres peut remplacer vos dll avec des versions plus anciennes. Les nouvelles versions auraient disparu. Ceci est communément appelé "dll hell", voir en.wikipedia.org/wiki/DLL_Hell
Adrian Grigore
1
Microsoft a abandonné WinSxS dans Visual Studio 2010 - les bibliothèques d'exécution sont désormais déployées soit en privé, soit dans system32 ( msdn.microsoft.com/en-us/library/vstudio/dd293574.aspx ).
BCran
8

Le problème que vous rencontrerez avec / MD est que la version cible du CRT peut ne pas être sur la machine de vos utilisateurs (en particulier si vous utilisez la dernière version de Visual Studio et que l'utilisateur a un système d'exploitation plus ancien).

Dans ce cas, vous devez trouver comment obtenir la bonne version sur leur machine.

i_am_jorf
la source
7

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

/ MT Définit _MT afin que les versions spécifiques au multithread des routines d'exécution soient sélectionnées à partir des fichiers d'en-tête standard (.h). Cette option oblige également le compilateur à placer le nom de bibliothèque LIBCMT.lib dans le fichier .obj afin que l'éditeur de liens utilise LIBCMT.lib pour résoudre les symboles externes. Soit / MT, soit / MD (ou leurs équivalents de débogage / MTd ou / MDd) est requis pour créer des programmes multithread.

/ MD Définit _MT et _DLL afin que les versions multithread et spécifiques à la DLL des routines d'exécution soient sélectionnées à partir des fichiers .h standard. Cette option oblige également le compilateur à placer le nom de bibliothèque MSVCRT.lib dans le fichier .obj.

Les applications compilées avec cette option sont liées statiquement à MSVCRT.lib. Cette bibliothèque fournit une couche de code qui permet à l'éditeur de liens de résoudre les références externes. Le code de travail réel est contenu dans MSVCR71.DLL, qui doit être disponible au moment de l'exécution pour les applications liées à MSVCRT.lib.

Lorsque / MD est utilisé avec _STATIC_CPPLIB défini (/ D_STATIC_CPPLIB), l'application se liera à la bibliothèque C ++ standard multithread statique (libcpmt.lib) au lieu de la version dynamique (msvcprt.lib) tout en se liant dynamiquement au CRT principal via msvcrt.lib.

Donc, si je l'interprète correctement, alors / MT lie statiquement et / MD lie dynamiquement.

Lothar
la source
La question était "lequel dois-je utiliser?", Ce n'est pas une réponse.
Leonard Inkret
1

Si vous créez un exécutable qui utilise d'autres dll ou bibliothèques que l'option / MD est préférable car de cette façon, tous les composants partageront la même bibliothèque. Bien sûr, cette option doit correspondre à tous les modules concernés, c'est-à-dire dll / lib / exe.

Si votre exécutable n'utilise aucune bibliothèque ou dll, c'est l'appel de n'importe qui. La différence n'est pas trop maintenant car l'aspect partage n'est pas en jeu.

Alors peut-être que vous pouvez démarrer l'application avec / MT car il n'y a pas de raison impérieuse sinon, mais quand il est temps d'ajouter une lib ou dll, vous pouvez le changer en / MD avec celui de la lib / dll, ce qui est facile.

zar
la source