Devo compilar com / MD ou / MT?

126

No Visual Studio, há os sinalizadores de compilação / MD e / MT que permitem escolher o tipo de biblioteca de tempo de execução C que você deseja.

Entendo a diferença na implementação, mas ainda não tenho certeza de qual usar. Quais são os prós / contras?

Uma vantagem do / MD que ouvi foi que isso permite que alguém atualize o tempo de execução (como talvez corrigir um problema de segurança) e meu aplicativo se beneficiará dessa atualização. Embora, para mim, isso quase pareça um recurso não: eu não quero que as pessoas mudem meu tempo de execução sem me permitir testar a nova versão!

Estou curioso sobre algumas coisas:

  • Como isso afetaria os tempos de construção? (presumivelmente / MT é um pouco mais lento?)
  • Quais são as outras implicações?
  • Qual deles a maioria das pessoas usa?
andy
fonte
1
Mais informações e sugestões podem ser encontradas em: stackoverflow.com/questions/787216
Weidenrinde

Respostas:

85

Ao vincular dinamicamente com / MD,

  • você está exposto a atualizações do sistema (boas ou más),
  • seu executável pode ser menor (já que não possui a biblioteca incorporada) e
  • Acredito que pelo menos o segmento de código de uma DLL seja compartilhado entre todos os processos que a estão usando ativamente (reduzindo a quantidade total de RAM consumida).

Também descobri que, na prática, ao trabalhar com bibliotecas binárias de terceiros vinculadas estaticamente que foram criadas com diferentes opções de tempo de execução, o / MT no aplicativo principal tende a causar conflitos com muito mais frequência do que o / MD (porque você terá problemas se o tempo de execução C estiver estaticamente vinculado várias vezes, especialmente se forem versões diferentes).

Mr Fooz
fonte
10
O bit de atualizações do sistema é um pouco reduzido pelo SxS. O EXE chega a declarar qual versão CRT ele quer (desejos, não fica - atualizações de segurança pode ignorar tal)
MSalters
1
Isso significa que, se eu compilar usando o MD e meu programa depender de alguma dll, o programa falhará se estiver sendo executado em um computador em que a dll de dependência não existe?
Gerrytan #
5
@gerrytan: Sim, você precisará garantir que as DLLs apropriadas usadas estejam presentes em todos os computadores que desejam executar o software. As soluções típicas para isso são fazer com que o usuário instale o pacote redistribuível apropriado da MSVC ou use um instalador que faça todo o trabalho.
Mr Fooz
@Royi Não tenho certeza, mas acho que /MTserá um pouco mais rápido em tempo de execução, já que seu aplicativo não precisa procurar a implementação da função de tempo de execução todas as vezes, não sou especialista nesse nível, mas tenho quase certeza de que Os SOs armazenam em cache as implementações de tempo de execução para que seu aplicativo use a versão em cache, portanto a diferença não será tão longe. NOTA: mencionei que não tenho certeza, portanto, não tome esse comentário como argumento.
Ahmed Kamal
34

Se você estiver usando DLLs, deverá procurar o CRT vinculado dinamicamente (/ MD).

Se você usar o CRT dinâmico para o seu .exe e todos os .dlls, todos compartilharão uma única implementação do CRT - o que significa que todos compartilharão um único heap e a memória do CRT alocada em um .exe / .dll. outro.

Se você usar o CRT estático para o seu .exe e todos os .dlls, todos receberão uma cópia separada do CRT - o que significa que todos usarão seu próprio heap de CRT para que a memória seja liberada no mesmo módulo em que foi alocado. Você também sofrerá com o inchaço do código (várias cópias do CRT) e a sobrecarga excessiva do tempo de execução (cada pilha aloca memória do sistema operacional para acompanhar seu estado, e a sobrecarga pode ser notada).

JoeG
fonte
20

Eu acredito que o padrão para projetos criados através do Visual Studio é / MD.

Se você usar / MT, seu executável não dependerá da presença de uma DLL no sistema de destino. Se você estiver agrupando isso em um instalador, provavelmente não será um problema e você pode ir de qualquer maneira.

Eu mesmo uso o / MT, para poder ignorar toda a bagunça da DLL.

PS Como observa o Sr. Fooz , é vital ser consistente. Se você estiver vinculando com outras bibliotecas, precisará usar a mesma opção que elas. Se você estiver usando uma DLL de terceiros, é quase certo que você precisará usar a versão DLL da biblioteca de tempo de execução.

Mark Ransom
fonte
14

Eu prefiro vincular estaticamente com / MT.

Mesmo que você obtenha um executável menor com / MD, você ainda precisará enviar um monte de DLLs para garantir que o usuário obtenha a versão correta para executar seu programa. E, no final, seu instalador será MAIOR do que ao vincular com / MT.

O que é ainda pior: se você optar por colocar suas bibliotecas de tempo de execução no diretório do Windows, mais cedo ou mais tarde o usuário instalará um novo aplicativo com diferentes bibliotecas e, com alguma má sorte, interromperá seu aplicativo.

Adrian Grigore
fonte
5
Muito má ideia "colocar suas bibliotecas de tempo de execução no diretório do Windows". Você pode quebrar outros aplicativos burros que fizeram o mesmo antes de você. Use o SxS e deixe o instalador lidar com isso ou use / MT.
MSalters
1
Concordo plenamente que é uma má ideia. Algumas pessoas fazem isso, então eu estava descrevendo por que isso não é uma boa ideia.
Adrian Grigore
@AdrianGrigore Por que um novo aplicativo com bibliotecas diferentes causaria uma interrupção no seu aplicativo? Se você usar a ligação / MD, você apenas começaria a carregar as novas versões das bibliotecas, certo?
rturrado 17/09/12
4
@rturrado: não é bem assim. Instalar outros aplicativos em cima do seu pode substituir suas DLLs com versões mais antigas. As versões mais recentes teriam desaparecido. Isso é comumente conhecido como "dll hell", consulte en.wikipedia.org/wiki/DLL_Hell
Adrian Grigore
1
A Microsoft desistiu do WinSxS no Visual Studio 2010 - as bibliotecas de tempo de execução agora são implantadas em particular ou no system32 ( msdn.microsoft.com/en-us/library/vstudio/dd293574.aspx ).
BCRAN
8

O problema que você encontrará com / MD é que a versão de destino do CRT pode não estar na máquina dos usuários (especialmente se você estiver usando a versão mais recente do Visual Studio e o usuário tiver um sistema operacional mais antigo).

Nesse caso, você precisa descobrir como obter a versão correta na máquina deles.

i_am_jorf
fonte
7

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

/ MT Define _MT para que versões específicas de multithread das rotinas de tempo de execução sejam selecionadas nos arquivos de cabeçalho padrão (.h). Essa opção também faz com que o compilador coloque o nome da biblioteca LIBCMT.lib no arquivo .obj, para que o vinculador use LIBCMT.lib para resolver símbolos externos. / MT ou / MD (ou seus equivalentes de depuração / MTd ou / MDd) são necessários para criar programas multithread.

/ MD Define _MT e _DLL para que as versões específicas das multithread e DLL das rotinas de tempo de execução sejam selecionadas nos arquivos .h padrão. Essa opção também faz com que o compilador coloque o nome da biblioteca MSVCRT.lib no arquivo .obj.

Os aplicativos compilados com esta opção estão vinculados estaticamente ao MSVCRT.lib. Essa biblioteca fornece uma camada de código que permite ao vinculador resolver referências externas. O código de trabalho real está contido no MSVCR71.DLL, que deve estar disponível em tempo de execução para aplicativos vinculados ao MSVCRT.lib.

Quando o / MD é usado com _STATIC_CPPLIB definido (/ D_STATIC_CPPLIB), o aplicativo é vinculado à Biblioteca C ++ Padrão multithread estática (libcpmt.lib) em vez da versão dinâmica (msvcprt.lib), enquanto ainda se vincula dinamicamente ao CRT principal por meio de msvcrt.lib.

Portanto, se eu estiver interpretando corretamente, os links / MT estaticamente e / MD serão dinamicamente.

Lothar
fonte
A pergunta era "qual devo usar?", Essa não é uma resposta.
Leonard Inkret
1

Se você estiver criando um executável que use outras DLLs ou bibliotecas que não a opção / MD, é preferível, pois dessa forma todos os componentes compartilharão a mesma biblioteca. Obviamente, esta opção deve corresponder a todos os módulos envolvidos, isto é, dll / lib / exe.

Se o seu executável não usa nenhuma lib ou dll do que a chamada de ninguém. A diferença não é grande agora, porque o aspecto de compartilhamento não está em jogo.

Então, talvez você possa iniciar o aplicativo com / MT, já que não há um motivo convincente, mas quando é hora de adicionar uma lib ou dll, você pode alterá-lo para / MD com o da lib / dll, o que é fácil.

zar
fonte