¿Debo compilar con / MD o / MT?

126

En Visual Studio, están los indicadores de compilación / MD y / MT que le permiten elegir qué tipo de biblioteca de tiempo de ejecución C desea.

Entiendo la diferencia en la implementación, pero todavía no estoy seguro de cuál usar. ¿Cuáles son los pros / contras?

Una de las ventajas de / MD que he escuchado es que esto permite que alguien actualice el tiempo de ejecución (como parchear un problema de seguridad) y mi aplicación se beneficiará de esta actualización. Aunque para mí, esto casi no parece una característica: ¡no quiero que la gente cambie mi tiempo de ejecución sin permitirme probar con la nueva versión!

Algunas cosas que tengo curiosidad sobre:

  • ¿Cómo afectaría esto a los tiempos de construcción? (presumiblemente / MT es un poco más lento?)
  • ¿Cuáles son las otras implicaciones?
  • ¿Cuál usa la mayoría de la gente?
andy
fuente
1
Puede encontrar más información y sugerencias en: stackoverflow.com/questions/787216
Weidenrinde

Respuestas:

85

Al vincular dinámicamente con / MD,

  • está expuesto a actualizaciones del sistema (para bien o para mal),
  • su ejecutable puede ser más pequeño (ya que no tiene la biblioteca incrustada), y
  • Creo que al menos el segmento de código de un archivo DLL se comparte entre todos los procesos que lo usan activamente (reduciendo la cantidad total de RAM consumida).

También he descubierto que, en la práctica, cuando se trabaja con bibliotecas de terceros binarias vinculadas estáticamente que se han creado con diferentes opciones de tiempo de ejecución, / MT en la aplicación principal tiende a causar conflictos con mucha más frecuencia que / MD (porque Tendrá problemas si el tiempo de ejecución de C está vinculado estáticamente varias veces, especialmente si son versiones diferentes).

Señor fooz
fuente
10
El bit de actualizaciones del sistema es algo reducido por SxS. El EXE llega a declarar cuál es la versión que quiere CRT (deseos, no consigue - actualizaciones de seguridad podrían invalidar este)
MSalters
1
¿Significa esto que si compilo usando MD y mi programa depende de algún dll, el programa fallará si se ejecuta en una computadora donde el dll de dependencia no existe?
gerrytan
55
@gerrytan: Sí, deberá asegurarse de que las DLL apropiadas que se utilizan estén presentes en todas las computadoras que desean ejecutar el software. Las soluciones típicas para esto son hacer que el usuario instale el paquete redistribuible MSVC apropiado, o use un instalador que haga todo el trabajo.
Sr. Fooz
@Royi No estoy seguro, pero creo que /MTserá un poco más rápido en tiempo de ejecución ya que su aplicación no necesita buscar la implementación de la función de tiempo de ejecución cada vez, no soy un experto en este nivel, pero estoy bastante seguro de que la mayoría de Los sistemas operativos almacenarán en caché las implementaciones de tiempo de ejecución para que su aplicación use la versión en caché, por lo que la diferencia no estará tan lejos, TENGA EN CUENTA que mencioné que no estoy seguro, así que no tome este comentario como argumento.
Ahmed Kamal
34

Si está utilizando DLL, entonces debe optar por el CRT vinculado dinámicamente (/ MD).

Si utiliza el CRT dinámico para su .exe y todos los .dlls, todos compartirán una única implementación del CRT, lo que significa que todos compartirán un único montón de CRT y la memoria asignada en un .exe / .dll puede liberarse otro.

Si usa el CRT estático para su .exe y todos los .dlls, todos obtendrán una copia separada del CRT, lo que significa que todos usarán su propio montón de CRT, por lo que la memoria debe liberarse en el mismo módulo en el que se encuentra. fue asignado. También sufrirá una acumulación de código (varias copias de la CRT) y una sobrecarga de tiempo de ejecución excesiva (cada montón asigna memoria del sistema operativo para realizar un seguimiento de su estado, y la sobrecarga puede ser notable).

JoeG
fuente
20

Creo que el valor predeterminado para proyectos creados a través de Visual Studio es / MD.

Si usa / MT, su ejecutable no dependerá de una DLL presente en el sistema de destino. Si está envolviendo esto en un instalador, probablemente no será un problema y puede ir en cualquier dirección.

Yo mismo uso / MT, para poder ignorar todo el desastre de DLL.

PD: Como señala el Sr. Fooz , es vital ser coherente. Si está vinculando con otras bibliotecas, debe usar la misma opción que ellas. Si está utilizando una DLL de terceros, es casi seguro que necesitará usar la versión DLL de la biblioteca en tiempo de ejecución.

Mark Ransom
fuente
14

Prefiero vincular estáticamente con / MT.

Aunque obtenga un ejecutable más pequeño con / MD, aún tiene que enviar un montón de archivos DLL para asegurarse de que el usuario obtenga la versión correcta para ejecutar su programa. Y al final su instalador será MÁS GRANDE que cuando se vincule con / MT.

Lo que es aún peor, si elige colocar sus bibliotecas de tiempo de ejecución en el directorio de Windows, tarde o temprano el usuario instalará una nueva aplicación con diferentes bibliotecas y, con cualquier mala suerte, romperá su aplicación.

Adrian Grigore
fuente
55
Muy mala idea para "poner sus bibliotecas de tiempo de ejecución en el directorio de Windows". Puede romper otras aplicaciones tontas que hicieron lo mismo antes que usted. Use SxS y deje que el instalador lo maneje, o quédese con / MT.
MSalters
1
Estoy totalmente de acuerdo en que es una mala idea. Sin embargo, algunas personas lo hacen, así que estaba describiendo por qué no es una buena idea.
Adrian Grigore
@AdrianGrigore ¿por qué una nueva aplicación con diferentes bibliotecas causaría una interrupción en su aplicación? Si usa el enlace / MD, simplemente comenzaría a cargar las nuevas versiones de las bibliotecas, ¿verdad?
rturrado
44
@rturrado: no del todo. Instalar otras aplicaciones sobre las tuyas podría sobrescribir tus archivos dlls con versiones anteriores. Las versiones más nuevas se habrían ido. Esto se conoce comúnmente como "dll hell", ver en.wikipedia.org/wiki/DLL_Hell
Adrian Grigore
1
Microsoft renunció a WinSxS en Visual Studio 2010: las bibliotecas de tiempo de ejecución ahora se implementan de forma privada o en system32 ( msdn.microsoft.com/en-us/library/vstudio/dd293574.aspx ).
BCran
8

El problema con el que se encontrará con / MD es que la versión de destino del CRT puede no estar en la máquina de sus usuarios (especialmente si está utilizando la última versión de Visual Studio y el usuario tiene un sistema operativo más antiguo).

En ese caso, tiene que descubrir cómo obtener la versión correcta en su máquina.

i_am_jorf
fuente
7

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

/ MT Define _MT para que se seleccionen versiones específicas de subprocesos múltiples de las rutinas de tiempo de ejecución de los archivos de encabezado estándar (.h). Esta opción también hace que el compilador coloque el nombre de la biblioteca LIBCMT.lib en el archivo .obj para que el vinculador use LIBCMT.lib para resolver símbolos externos. Se requiere / MT o / MD (o sus equivalentes de depuración / MTd o / MDd) para crear programas multiproceso.

/ MD Define _MT y _DLL para que se seleccionen las versiones de las rutinas de tiempo de ejecución de subprocesos múltiples y específicos de los archivos .h estándar. Esta opción también hace que el compilador coloque el nombre de la biblioteca MSVCRT.lib en el archivo .obj.

Las aplicaciones compiladas con esta opción están vinculadas estáticamente a MSVCRT.lib. Esta biblioteca proporciona una capa de código que permite al vinculador resolver referencias externas. El código de trabajo real está contenido en MSVCR71.DLL, que debe estar disponible en tiempo de ejecución para las aplicaciones vinculadas con MSVCRT.lib.

Cuando / MD se usa con _STATIC_CPPLIB definido (/ D_STATIC_CPPLIB) hará que la aplicación se vincule con la biblioteca estándar de múltiples hilos estática de C ++ (libcpmt.lib) en lugar de la versión dinámica (msvcprt.lib) mientras se vincula dinámicamente al CRT principal a través de msvcrt.lib.

Entonces, si lo estoy interpretando correctamente, entonces / MT enlaza estáticamente y / MD enlaza dinámicamente.

lothar
fuente
La pregunta era "¿cuál debería usar?", Esta no es una respuesta.
Leonard Inkret
1

Si está compilando archivos ejecutables que usan otras dlls o libs que la opción / MD es preferible porque de esa manera todos los componentes compartirán la misma biblioteca. Por supuesto, esta opción debe coincidir con todos los módulos involucrados, es decir, dll / lib / exe.

Si su ejecutable no usa ninguna lib o dll, entonces es la llamada de cualquiera. La diferencia no es demasiado ahora porque el aspecto de compartir no está en juego.

Entonces, tal vez pueda iniciar la aplicación con / MT, ya que no hay una razón convincente de lo contrario, pero cuando llegue el momento de agregar una lib o dll, puede cambiarla a / MD con la de lib / dll, que es fácil.

zar
fuente